pipeproc
Version:
Multi-process log processing for nodejs
125 lines (124 loc) • 4.06 kB
JavaScript
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const net_1 = require("net");
const tls_1 = require("tls");
const debug_1 = __importDefault(require("debug"));
const uuid_1 = require("uuid");
const fs_1 = require("fs");
const xpipe_1 = require("./xpipe");
const send_1 = require("./send");
const d = debug_1.default("pipeproc:socket:bind");
function bind(address, options, callback) {
//tslint:disable no-any
const messageListeners = [];
//tslint:enable no-any
const socketMap = new Map();
const server = options.tls ? tls_1.createServer({
ca: options.tls.ca,
key: options.tls.key,
cert: options.tls.cert,
requestCert: true,
rejectUnauthorized: true
}, connectionHandler) : net_1.createServer(connectionHandler);
function connectionHandler(socket) {
d("new connection", socket.address());
const binder = createBinder(socket);
socketMap.set(socket, binder);
socket.setEncoding("utf8");
socket.setNoDelay(true);
socket.on("end", function () {
socketMap.delete(socket);
});
socket.on("close", function () {
socketMap.delete(socket);
});
socket.on("error", function (err) {
d(err);
});
socket.on("data", function (chunk) {
const data = binder.buffer + chunk;
const messages = data.split("%EOM%");
binder.buffer = messages.pop() || "";
messages.forEach(function (msg) {
let parsedData;
try {
parsedData = JSON.parse(msg);
}
catch (e) {
d("Socket data parsing error:", e, msg);
return;
}
messageListeners.forEach(function (listener) {
listener(parsedData, binder);
});
});
});
}
const socketServer = {
close: function () {
if (address.includes("ipc://")) {
const socketPath = address.replace("ipc://", "");
try {
fs_1.unlinkSync(socketPath);
}
catch (_e) { }
}
server.close();
d("message socket closed");
},
onMessage: function (listener) {
messageListeners.push(listener);
}
};
let connectionRetries = 0;
let cbCalled = false;
server.on("error", function (err) {
if (err.code === "EADDRINUSE" && address.includes("ipc://") && connectionRetries < 3) {
const socketPath = address.replace("ipc://", "");
try {
fs_1.unlinkSync(socketPath);
setTimeout(function () {
connectionRetries += 1;
startServer(server, address);
}, 100);
}
catch (_e) { }
}
else {
d("Socket error:", err);
if (!cbCalled) {
cbCalled = true;
callback(err);
}
}
});
server.once("listening", function () {
d("Socket server is listening on", address);
if (!cbCalled) {
cbCalled = true;
callback(null, socketServer);
}
});
startServer(server, address);
}
exports.bind = bind;
function startServer(server, address) {
if (address.includes("ipc://")) {
const socketPath = address.replace("ipc://", "");
server.listen(xpipe_1.xpipe(socketPath));
}
else if (address.includes("tcp://")) {
const parts = address.replace("tcp://", "").split(":");
server.listen(parseInt(parts[1]), parts[0]);
}
}
function createBinder(socket) {
return {
id: uuid_1.v4(),
send: send_1.getSender(socket),
buffer: ""
};
}
;