UNPKG

node-opcua-transport

Version:

pure nodejs OPCUA SDK - module transport

162 lines (161 loc) 6.31 kB
"use strict"; /** * @module node-opcua-transport */ var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.ClientTCP_transport = void 0; const node_net_1 = require("node:net"); const node_os_1 = __importDefault(require("node:os")); const node_util_1 = require("node:util"); const chalk_1 = __importDefault(require("chalk")); const node_opcua_assert_1 = require("node-opcua-assert"); const node_opcua_debug_1 = require("node-opcua-debug"); const client_transport_base_1 = require("./client_transport_base"); const tcp_transport_1 = require("./tcp_transport"); const tools_1 = require("./tools"); const doDebug = (0, node_opcua_debug_1.checkDebugFlag)(__filename); const debugLog = (0, node_opcua_debug_1.make_debugLog)(__filename); const errorLog = (0, node_opcua_debug_1.make_errorLog)(__filename); const gHostname = node_os_1.default.hostname(); function createClientSocket(endpointUrl, timeout) { // create a socket based on Url const ep = (0, tools_1.parseEndpointUrl)(endpointUrl); const port = parseInt(ep.port || "4840", 10); const hostname = ep.hostname; let socket; switch (ep.protocol) { case "opc.tcp:": socket = (0, node_net_1.createConnection)({ host: hostname, port, timeout }, () => { doDebug && debugLog(`connected to server! ${hostname}:${port} timeout:${timeout} `); }); socket.setNoDelay(false); socket.setKeepAlive(true, timeout >> 1); return socket; case "fake:": (0, node_opcua_assert_1.assert)(ep.protocol === "fake:", " Unsupported transport protocol"); socket = (0, tcp_transport_1.getFakeTransport)(); return socket; default: { const msg = `[NODE-OPCUA-E05] this transport protocol is not supported :${ep.protocol}`; errorLog(msg); throw new Error(msg); } } } /** * a ClientTCP_transport connects to a remote server socket and * initiates a communication with a HEL/ACK transaction. * It negotiates the communication parameters with the other end. * @example * * ```javascript * const transport = ClientTCP_transport(url); * * transport.timeout = 10000; * * transport.connect(function (err)) { * if (err) { * // cannot connect * } else { * // connected * * } * }); * .... * * transport.write(message_chunk, 'F'); * * .... * * transport.on("chunk", function (message_chunk) { * // do something with chunk from server... * }); * * * ``` * * */ class ClientTCP_transport extends client_transport_base_1.ClientTransportBase { dispose() { /* c8 ignore next */ doDebug && debugLog(" ClientTCP_transport disposed"); super.dispose(); } connect(endpointUrl, callback) { this.endpointUrl = endpointUrl; this.serverUri = `urn:${gHostname}:Sample`; /* c8 ignore next */ doDebug && debugLog(chalk_1.default.cyan(`ClientTCP_transport#connect(endpointUrl = ${endpointUrl})`)); let socket = null; try { // validate the URL upfront so a parse error is reported synchronously (0, tools_1.parseEndpointUrl)(endpointUrl); socket = createClientSocket(endpointUrl, this.timeout); socket.setTimeout(this.timeout >> 1, () => { this.forceConnectionBreak(); }); } catch (err) { /* c8 ignore next */ doDebug && debugLog("CreateClientSocket has failed"); callback(err); return; } const _on_socket_connect = () => { /* c8 ignore next */ doDebug && debugLog("entering _on_socket_connect"); _remove_connect_listeners(); this._perform_HEL_ACK_transaction((err) => { if (!err) { /* c8 ignore next */ if (!this._socket) { return callback(new Error("Abandoned")); } // install the post-connect "connection break" detector inherited from ClientTransportBase this._install_post_connect_error_handler(endpointUrl); /** * notify the observers that the transport is connected (the socket is connected and the the HEL/ACK * transaction has been done) * @event connect */ this.emit("connect"); } else { debugLog("_perform_HEL_ACK_transaction has failed with err=", err.message); } callback(err); }); }; const _on_socket_error_for_connect = (err) => { // this handler will catch attempt to connect to an inaccessible address. /* c8 ignore next */ doDebug && debugLog(chalk_1.default.cyan("ClientTCP_transport#connect - _on_socket_error_for_connect"), err.message); (0, node_opcua_assert_1.assert)(node_util_1.types.isNativeError(err)); _remove_connect_listeners(); callback(err); }; const _on_socket_end_for_connect = () => { /* c8 ignore next */ doDebug && debugLog(chalk_1.default.cyan("ClientTCP_transport#connect -> _on_socket_end_for_connect Socket has been closed by server")); }; const _remove_connect_listeners = () => { /* c8 ignore next */ if (!this._socket) { return; } this._socket.removeListener("error", _on_socket_error_for_connect); this._socket.removeListener("end", _on_socket_end_for_connect); }; this._install_socket(socket); this._socket?.once("error", _on_socket_error_for_connect); this._socket?.once("end", _on_socket_end_for_connect); this._socket?.once("connect", _on_socket_connect); } } exports.ClientTCP_transport = ClientTCP_transport; //# sourceMappingURL=client_tcp_transport.js.map