@fibercom/routeros-api
Version:
Robust MikroTik RouterOS API client for Node.js and TypeScript
175 lines • 14.6 kB
JavaScript
"use strict";
var __rest = (this && this.__rest) || function (s, e) {
var t = {};
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
t[p] = s[p];
if (s != null && typeof Object.getOwnPropertySymbols === "function")
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
t[p[i]] = s[p[i]];
}
return t;
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.Connector = void 0;
const events_1 = require("events");
const net_1 = require("net");
const tls = require("tls");
const Receiver_1 = require("./Receiver");
const Transmitter_1 = require("./Transmitter");
const RosException_1 = require("../RosException");
const debug = require("debug");
const info = debug("routeros-api:connector:info");
const error = debug("routeros-api:connector:error");
class Connector extends events_1.EventEmitter {
constructor(options) {
var _a, _b, _c;
super();
this.debug = false;
this.connected = false;
this.connecting = false;
this.host = options.host;
this.port = (_a = options.port) !== null && _a !== void 0 ? _a : (options.tls ? 8729 : 8728);
this.timeout = (_b = options.timeout) !== null && _b !== void 0 ? _b : 5;
this.debug = (_c = options.debug) !== null && _c !== void 0 ? _c : false;
const tlsOptions = options.tls === true ? {} : options.tls;
if (typeof tlsOptions === "object") {
const { pskCallback } = tlsOptions, safeTls = __rest(tlsOptions, ["pskCallback"]);
this.tlsOptions = safeTls;
}
}
log(message) {
if (this.debug)
console.debug(message);
}
connect() {
if (this.connected || this.connecting) {
this.log("[DEBUG] Already connected or connecting.");
return Promise.resolve(this);
}
this.connecting = true;
return new Promise((resolve, reject) => {
var _a, _b, _c, _d;
const timeoutMs = this.timeout * 1000;
const timeout = setTimeout(() => {
var _a;
this.log("[DEBUG] Connection timeout triggered.");
(_a = this.socket) === null || _a === void 0 ? void 0 : _a.destroy();
this.connecting = false;
rejectOnce(new RosException_1.RosException("SOCKTMOUT", {
message: "Connection timed out. API may be disabled, filtered, or unreachable.",
seconds: this.timeout.toString(),
}));
}, timeoutMs);
let resolved = false;
const resolveOnce = () => {
if (!resolved) {
resolved = true;
clearTimeout(timeout);
resolve(this);
}
};
const rejectOnce = (err) => {
if (!resolved) {
resolved = true;
clearTimeout(timeout);
reject(err);
}
};
const onConnected = () => {
this.log("[DEBUG] Socket connect event fired.");
this.connecting = false;
this.connected = true;
this.transmitter.runPool();
this.emit("connected", this);
resolveOnce(); // ✅ resolve immediately
};
const onError = (err) => {
var _a;
this.connecting = false;
this.connected = false;
(_a = this.socket) === null || _a === void 0 ? void 0 : _a.destroy();
const code = (err === null || err === void 0 ? void 0 : err.code) || (err === null || err === void 0 ? void 0 : err.errno) || "UNKNOWN";
this.log(`[DEBUG] Socket error: ${code}`);
const socketError = new RosException_1.RosException("APIFORBIDDEN", {
message: "Connection failed. API may be disabled or filtered. Code: " +
code,
});
if (resolved)
this.emit("error", socketError, this);
else
rejectOnce(socketError);
};
try {
if (this.tlsOptions) {
this.log("[DEBUG] Using TLS socket");
this.socket = tls.connect(this.port, this.host, this.tlsOptions, onConnected);
}
else {
this.log("[DEBUG] Using plain TCP socket");
this.socket = new net_1.Socket();
this.socket.connect(this.port, this.host);
this.socket.once("connect", onConnected);
}
this.transmitter = new Transmitter_1.Transmitter(this.socket);
this.receiver = new Receiver_1.Receiver(this.socket);
this.socket.on("data", (data) => {
this.onData(data);
});
this.socket.once("end", this.onEnd.bind(this));
this.socket.once("close", this.onClose.bind(this));
this.socket.once("timeout", this.onTimeout.bind(this));
this.socket.once("error", onError);
(_b = (_a = this.socket).setTimeout) === null || _b === void 0 ? void 0 : _b.call(_a, timeoutMs);
(_d = (_c = this.socket).setKeepAlive) === null || _d === void 0 ? void 0 : _d.call(_c, true);
}
catch (e) {
const message = e instanceof Error ? e.message : String(e);
rejectOnce(new RosException_1.RosException("SOCKFAIL", { message }));
}
});
}
write(data) {
for (const line of data)
this.transmitter.write(line);
this.transmitter.write(null);
return this;
}
read(tag, cb) {
this.receiver.read(tag, cb);
}
stopRead(tag) {
this.receiver.stop(tag);
}
close() {
var _a;
(_a = this.socket) === null || _a === void 0 ? void 0 : _a.end();
}
destroy() {
var _a;
(_a = this.socket) === null || _a === void 0 ? void 0 : _a.destroy();
this.removeAllListeners();
}
onEnd() {
this.log("[DEBUG] Socket end event fired.");
}
onClose() {
this.connected = false;
this.connecting = false;
this.emit("close", this);
}
onTimeout() {
this.connected = false;
this.connecting = false;
const timeoutErr = new RosException_1.RosException("SOCKTMOUT", {
seconds: this.timeout,
});
this.emit("timeout", timeoutErr, this);
this.destroy();
}
onData(data) {
this.receiver.processRawData(data);
}
}
exports.Connector = Connector;
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiQ29ubmVjdG9yLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL2Nvbm5lY3Rvci9Db25uZWN0b3IudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7Ozs7Ozs7QUFBQSxtQ0FBc0M7QUFDdEMsNkJBQTZCO0FBQzdCLDJCQUEyQjtBQUMzQix5Q0FBc0M7QUFDdEMsK0NBQTRDO0FBQzVDLGtEQUErQztBQUMvQywrQkFBZ0M7QUFHaEMsTUFBTSxJQUFJLEdBQUcsS0FBSyxDQUFDLDZCQUE2QixDQUFDLENBQUM7QUFDbEQsTUFBTSxLQUFLLEdBQUcsS0FBSyxDQUFDLDhCQUE4QixDQUFDLENBQUM7QUFFcEQsTUFBYSxTQUFVLFNBQVEscUJBQVk7SUFhekMsWUFBWSxPQUFvQjs7UUFDOUIsS0FBSyxFQUFFLENBQUM7UUFWSCxVQUFLLEdBQVksS0FBSyxDQUFDO1FBS3RCLGNBQVMsR0FBWSxLQUFLLENBQUM7UUFDM0IsZUFBVSxHQUFZLEtBQUssQ0FBQztRQUtsQyxJQUFJLENBQUMsSUFBSSxHQUFHLE9BQU8sQ0FBQyxJQUFJLENBQUM7UUFDekIsSUFBSSxDQUFDLElBQUksR0FBRyxNQUFBLE9BQU8sQ0FBQyxJQUFJLG1DQUFJLENBQUMsT0FBTyxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsQ0FBQztRQUN4RCxJQUFJLENBQUMsT0FBTyxHQUFHLE1BQUEsT0FBTyxDQUFDLE9BQU8sbUNBQUksQ0FBQyxDQUFDO1FBQ3BDLElBQUksQ0FBQyxLQUFLLEdBQUcsTUFBQSxPQUFPLENBQUMsS0FBSyxtQ0FBSSxLQUFLLENBQUM7UUFFcEMsTUFBTSxVQUFVLEdBQUcsT0FBTyxDQUFDLEdBQUcsS0FBSyxJQUFJLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsT0FBTyxDQUFDLEdBQUcsQ0FBQztRQUMzRCxJQUFJLE9BQU8sVUFBVSxLQUFLLFFBQVEsRUFBRSxDQUFDO1lB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