node-opcua-transport
Version:
pure nodejs OPCUA SDK - module transport
106 lines • 4.43 kB
JavaScript
;
/**
* @module node-opcua-transport
*/
Object.defineProperty(exports, "__esModule", { value: true });
exports.decodeMessage = decodeMessage;
exports.packTcpMessage = packTcpMessage;
exports.parseEndpointUrl = parseEndpointUrl;
exports.is_valid_endpointUrl = is_valid_endpointUrl;
exports.writeTCPMessageHeader = writeTCPMessageHeader;
const node_opcua_assert_1 = require("node-opcua-assert");
const node_opcua_binary_stream_1 = require("node-opcua-binary-stream");
const node_opcua_buffer_utils_1 = require("node-opcua-buffer-utils");
const node_opcua_chunkmanager_1 = require("node-opcua-chunkmanager");
const TCPErrorMessage_1 = require("./TCPErrorMessage");
function is_valid_msg_type(msgType) {
(0, node_opcua_assert_1.assert)([
"HEL",
"ACK",
"ERR", // Connection Layer
"OPN",
"MSG",
"CLO" // OPC Unified Architecture, Part 6 page 36
].indexOf(msgType) >= 0, `invalid message type ${msgType}`);
return true;
}
function decodeMessage(stream, classNameConstructor) {
(0, node_opcua_assert_1.assert)(stream instanceof node_opcua_binary_stream_1.BinaryStream);
(0, node_opcua_assert_1.assert)(classNameConstructor instanceof Function, ` expecting a function for ${classNameConstructor}`);
const header = (0, node_opcua_chunkmanager_1.readMessageHeader)(stream);
(0, node_opcua_assert_1.assert)(stream.length === 8);
let obj;
if (header.msgType === "ERR") {
obj = new TCPErrorMessage_1.TCPErrorMessage();
obj.decode(stream);
return obj;
}
else {
obj = new classNameConstructor();
obj.decode(stream);
return obj;
}
}
function packTcpMessage(msgType, encodableObject) {
(0, node_opcua_assert_1.assert)(is_valid_msg_type(msgType));
const messageChunk = (0, node_opcua_buffer_utils_1.createFastUninitializedBuffer)(encodableObject.binaryStoreSize() + 8);
// encode encode-ableObject in a packet
const stream = new node_opcua_binary_stream_1.BinaryStream(messageChunk);
encodeMessage(msgType, encodableObject, stream);
return messageChunk;
}
// opc.tcp://hostname:51210/UA/SampleServer
function parseEndpointUrl(endpointUrl) {
// Replace non-standard protocols (e.g. opc.tcp:) with http:
// so the WHATWG URL parser can handle them, then restore the
// original protocol in the result.
const protocolMatch = endpointUrl.match(/^([a-z][a-z0-9.+-]*):/i);
if (!protocolMatch) {
throw new Error(`Invalid endpoint url ${endpointUrl}`);
}
const originalProtocol = `${protocolMatch[1].toLowerCase()}:`;
const normalizedUrl = endpointUrl.replace(/^[a-z][a-z0-9.+-]*:/i, "http:");
let parsed;
try {
parsed = new URL(normalizedUrl);
}
catch {
throw new Error(`Invalid endpoint url ${endpointUrl}`);
}
if (!parsed.hostname) {
throw new Error(`Invalid endpoint url ${endpointUrl}`);
}
return {
protocol: originalProtocol,
hostname: parsed.hostname,
port: parsed.port || null,
pathname: parsed.pathname !== "/" ? parsed.pathname : null,
auth: parsed.username ? (parsed.password ? `${parsed.username}:${parsed.password}` : parsed.username) : null,
href: endpointUrl
};
}
function is_valid_endpointUrl(endpointUrl) {
const e = parseEndpointUrl(endpointUrl);
return Object.hasOwn(e, "hostname");
}
function writeTCPMessageHeader(msgType, chunkType, totalLength, stream) {
if (stream instanceof Buffer) {
stream = new node_opcua_binary_stream_1.BinaryStream(stream);
}
(0, node_opcua_assert_1.assert)(is_valid_msg_type(msgType));
(0, node_opcua_assert_1.assert)(["A", "F", "C"].indexOf(chunkType) !== -1);
stream.writeUInt8(msgType.charCodeAt(0));
stream.writeUInt8(msgType.charCodeAt(1));
stream.writeUInt8(msgType.charCodeAt(2));
// Chunk type
stream.writeUInt8(chunkType.charCodeAt(0)); // reserved
stream.writeUInt32(totalLength);
}
function encodeMessage(msgType, messageContent, stream) {
// the length of the message, in bytes. (includes the 8 bytes of the message header)
const totalLength = messageContent.binaryStoreSize() + 8;
writeTCPMessageHeader(msgType, "F", totalLength, stream);
messageContent.encode(stream);
(0, node_opcua_assert_1.assert)(totalLength === stream.length, "invalid message size");
}
//# sourceMappingURL=tools.js.map