Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

node-opcua-transport

Package Overview
Dependencies
Maintainers
1
Versions
221
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

node-opcua-transport - npm Package Compare versions

Comparing version 2.13.0 to 2.15.0

81

dist/source/AcknowledgeMessage.js

@@ -28,47 +28,44 @@ "use strict";

});
let AcknowledgeMessage = /** @class */ (() => {
class AcknowledgeMessage extends node_opcua_factory_1.BaseUAObject {
constructor(options) {
options = options || {};
super();
const schema = schemaAcknowledgeMessage;
/* istanbul ignore next */
if (node_opcua_factory_1.parameters.debugSchemaHelper) {
node_opcua_factory_1.check_options_correctness_against_schema(this, schema, options);
}
this.protocolVersion = node_opcua_factory_1.initialize_field(schema.fields[0], options.protocolVersion);
this.receiveBufferSize = node_opcua_factory_1.initialize_field(schema.fields[1], options.receiveBufferSize);
this.sendBufferSize = node_opcua_factory_1.initialize_field(schema.fields[2], options.sendBufferSize);
this.maxMessageSize = node_opcua_factory_1.initialize_field(schema.fields[3], options.maxMessageSize);
this.maxChunkCount = node_opcua_factory_1.initialize_field(schema.fields[4], options.maxChunkCount);
class AcknowledgeMessage extends node_opcua_factory_1.BaseUAObject {
constructor(options) {
options = options || {};
super();
const schema = schemaAcknowledgeMessage;
/* istanbul ignore next */
if (node_opcua_factory_1.parameters.debugSchemaHelper) {
node_opcua_factory_1.check_options_correctness_against_schema(this, schema, options);
}
encode(stream) {
super.encode(stream);
node_opcua_basic_types_1.encodeUInt32(this.protocolVersion, stream);
node_opcua_basic_types_1.encodeUInt32(this.receiveBufferSize, stream);
node_opcua_basic_types_1.encodeUInt32(this.sendBufferSize, stream);
node_opcua_basic_types_1.encodeUInt32(this.maxMessageSize, stream);
node_opcua_basic_types_1.encodeUInt32(this.maxChunkCount, stream);
}
decode(stream) {
// call base class implementation first
super.decode(stream);
this.protocolVersion = node_opcua_basic_types_1.decodeUInt32(stream);
this.receiveBufferSize = node_opcua_basic_types_1.decodeUInt32(stream);
this.sendBufferSize = node_opcua_basic_types_1.decodeUInt32(stream);
this.maxMessageSize = node_opcua_basic_types_1.decodeUInt32(stream);
this.maxChunkCount = node_opcua_basic_types_1.decodeUInt32(stream);
}
this.protocolVersion = node_opcua_factory_1.initialize_field(schema.fields[0], options.protocolVersion);
this.receiveBufferSize = node_opcua_factory_1.initialize_field(schema.fields[1], options.receiveBufferSize);
this.sendBufferSize = node_opcua_factory_1.initialize_field(schema.fields[2], options.sendBufferSize);
this.maxMessageSize = node_opcua_factory_1.initialize_field(schema.fields[3], options.maxMessageSize);
this.maxChunkCount = node_opcua_factory_1.initialize_field(schema.fields[4], options.maxChunkCount);
}
AcknowledgeMessage.possibleFields = [
"protocolVersion",
"receiveBufferSize",
"sendBufferSize",
"maxMessageSize",
"maxChunkCount"
];
AcknowledgeMessage.schema = schemaAcknowledgeMessage;
return AcknowledgeMessage;
})();
encode(stream) {
super.encode(stream);
node_opcua_basic_types_1.encodeUInt32(this.protocolVersion, stream);
node_opcua_basic_types_1.encodeUInt32(this.receiveBufferSize, stream);
node_opcua_basic_types_1.encodeUInt32(this.sendBufferSize, stream);
node_opcua_basic_types_1.encodeUInt32(this.maxMessageSize, stream);
node_opcua_basic_types_1.encodeUInt32(this.maxChunkCount, stream);
}
decode(stream) {
// call base class implementation first
super.decode(stream);
this.protocolVersion = node_opcua_basic_types_1.decodeUInt32(stream);
this.receiveBufferSize = node_opcua_basic_types_1.decodeUInt32(stream);
this.sendBufferSize = node_opcua_basic_types_1.decodeUInt32(stream);
this.maxMessageSize = node_opcua_basic_types_1.decodeUInt32(stream);
this.maxChunkCount = node_opcua_basic_types_1.decodeUInt32(stream);
}
}
exports.AcknowledgeMessage = AcknowledgeMessage;
AcknowledgeMessage.possibleFields = [
"protocolVersion",
"receiveBufferSize",
"sendBufferSize",
"maxMessageSize",
"maxChunkCount"
];
AcknowledgeMessage.schema = schemaAcknowledgeMessage;
//# sourceMappingURL=AcknowledgeMessage.js.map

@@ -41,49 +41,46 @@ "use strict";

});
let HelloMessage = /** @class */ (() => {
class HelloMessage extends node_opcua_factory_1.BaseUAObject {
constructor(options) {
options = options || {};
super();
const schema = schemaHelloMessage;
/* istanbul ignore next */
if (node_opcua_factory_1.parameters.debugSchemaHelper) {
node_opcua_factory_1.check_options_correctness_against_schema(this, schema, options);
}
this.protocolVersion = node_opcua_factory_1.initialize_field(schema.fields[0], options.protocolVersion);
this.receiveBufferSize = node_opcua_factory_1.initialize_field(schema.fields[1], options.receiveBufferSize);
this.sendBufferSize = node_opcua_factory_1.initialize_field(schema.fields[2], options.sendBufferSize);
this.maxMessageSize = node_opcua_factory_1.initialize_field(schema.fields[3], options.maxMessageSize);
this.maxChunkCount = node_opcua_factory_1.initialize_field(schema.fields[4], options.maxChunkCount);
this.endpointUrl = node_opcua_factory_1.initialize_field(schema.fields[5], options.endpointUrl);
class HelloMessage extends node_opcua_factory_1.BaseUAObject {
constructor(options) {
options = options || {};
super();
const schema = schemaHelloMessage;
/* istanbul ignore next */
if (node_opcua_factory_1.parameters.debugSchemaHelper) {
node_opcua_factory_1.check_options_correctness_against_schema(this, schema, options);
}
encode(stream) {
super.encode(stream);
node_opcua_basic_types_1.encodeUInt32(this.protocolVersion, stream);
node_opcua_basic_types_1.encodeUInt32(this.receiveBufferSize, stream);
node_opcua_basic_types_1.encodeUInt32(this.sendBufferSize, stream);
node_opcua_basic_types_1.encodeUInt32(this.maxMessageSize, stream);
node_opcua_basic_types_1.encodeUInt32(this.maxChunkCount, stream);
node_opcua_basic_types_1.encodeUAString(this.endpointUrl, stream);
}
decode(stream) {
super.decode(stream);
this.protocolVersion = node_opcua_basic_types_1.decodeUInt32(stream);
this.receiveBufferSize = node_opcua_basic_types_1.decodeUInt32(stream);
this.sendBufferSize = node_opcua_basic_types_1.decodeUInt32(stream);
this.maxMessageSize = node_opcua_basic_types_1.decodeUInt32(stream);
this.maxChunkCount = node_opcua_basic_types_1.decodeUInt32(stream);
this.endpointUrl = node_opcua_basic_types_1.decodeUAString(stream);
}
this.protocolVersion = node_opcua_factory_1.initialize_field(schema.fields[0], options.protocolVersion);
this.receiveBufferSize = node_opcua_factory_1.initialize_field(schema.fields[1], options.receiveBufferSize);
this.sendBufferSize = node_opcua_factory_1.initialize_field(schema.fields[2], options.sendBufferSize);
this.maxMessageSize = node_opcua_factory_1.initialize_field(schema.fields[3], options.maxMessageSize);
this.maxChunkCount = node_opcua_factory_1.initialize_field(schema.fields[4], options.maxChunkCount);
this.endpointUrl = node_opcua_factory_1.initialize_field(schema.fields[5], options.endpointUrl);
}
HelloMessage.possibleFields = [
"protocolVersion",
"receiveBufferSize",
"sendBufferSize",
"maxMessageSize",
"maxChunkCount",
"endpointUrl"
];
return HelloMessage;
})();
encode(stream) {
super.encode(stream);
node_opcua_basic_types_1.encodeUInt32(this.protocolVersion, stream);
node_opcua_basic_types_1.encodeUInt32(this.receiveBufferSize, stream);
node_opcua_basic_types_1.encodeUInt32(this.sendBufferSize, stream);
node_opcua_basic_types_1.encodeUInt32(this.maxMessageSize, stream);
node_opcua_basic_types_1.encodeUInt32(this.maxChunkCount, stream);
node_opcua_basic_types_1.encodeUAString(this.endpointUrl, stream);
}
decode(stream) {
super.decode(stream);
this.protocolVersion = node_opcua_basic_types_1.decodeUInt32(stream);
this.receiveBufferSize = node_opcua_basic_types_1.decodeUInt32(stream);
this.sendBufferSize = node_opcua_basic_types_1.decodeUInt32(stream);
this.maxMessageSize = node_opcua_basic_types_1.decodeUInt32(stream);
this.maxChunkCount = node_opcua_basic_types_1.decodeUInt32(stream);
this.endpointUrl = node_opcua_basic_types_1.decodeUAString(stream);
}
}
exports.HelloMessage = HelloMessage;
HelloMessage.possibleFields = [
"protocolVersion",
"receiveBufferSize",
"sendBufferSize",
"maxMessageSize",
"maxChunkCount",
"endpointUrl"
];
//# sourceMappingURL=HelloMessage.js.map

@@ -47,172 +47,169 @@ "use strict";

*/
let ServerTCP_transport = /** @class */ (() => {
class ServerTCP_transport extends tcp_transport_1.TCP_transport {
constructor() {
super();
this._aborted = 0;
this._helloReceived = false;
this.receiveBufferSize = 0;
this.sendBufferSize = 0;
this.maxMessageSize = 0;
this.maxChunkCount = 0;
this.protocolVersion = 0;
class ServerTCP_transport extends tcp_transport_1.TCP_transport {
constructor() {
super();
this._aborted = 0;
this._helloReceived = false;
this.receiveBufferSize = 0;
this.sendBufferSize = 0;
this.maxMessageSize = 0;
this.maxChunkCount = 0;
this.protocolVersion = 0;
}
/**
* Initialize the server transport.
*
*
* The ServerTCP_transport initialisation process starts by waiting for the client to send a "HEL" message.
*
* The ServerTCP_transport replies with a "ACK" message and then start waiting for further messages of any size.
*
* The callback function received an error:
* - if no message from the client is received within the ```self.timeout``` period,
* - or, if the connection has dropped within the same interval.
* - if the protocol version specified within the HEL message is invalid or is greater
* than ```self.protocolVersion```
*
*
*/
init(socket, callback) {
if (debugLog) {
debugLog(chalk.cyan("init socket"));
}
/**
* Initialize the server transport.
*
*
* The ServerTCP_transport initialisation process starts by waiting for the client to send a "HEL" message.
*
* The ServerTCP_transport replies with a "ACK" message and then start waiting for further messages of any size.
*
* The callback function received an error:
* - if no message from the client is received within the ```self.timeout``` period,
* - or, if the connection has dropped within the same interval.
* - if the protocol version specified within the HEL message is invalid or is greater
* than ```self.protocolVersion```
*
*
*/
init(socket, callback) {
if (debugLog) {
debugLog(chalk.cyan("init socket"));
}
node_opcua_assert_1.assert(!this._socket, "init already called!");
node_opcua_assert_1.assert(_.isFunction(callback), "expecting a valid callback ");
this._install_socket(socket);
this._install_HEL_message_receiver(callback);
node_opcua_assert_1.assert(!this._socket, "init already called!");
node_opcua_assert_1.assert(_.isFunction(callback), "expecting a valid callback ");
this._install_socket(socket);
this._install_HEL_message_receiver(callback);
}
abortWithError(statusCode, extraErrorDescription, callback) {
return this._abortWithError(statusCode, extraErrorDescription, callback);
}
_abortWithError(statusCode, extraErrorDescription, callback) {
if (debugLog) {
debugLog(chalk.cyan("_abortWithError"));
}
abortWithError(statusCode, extraErrorDescription, callback) {
return this._abortWithError(statusCode, extraErrorDescription, callback);
node_opcua_assert_1.assert(_.isFunction(callback), "expecting a callback");
/* istanbul ignore else */
if (!this._aborted) {
setTimeout(() => {
this._aborted = 1;
// send the error message and close the connection
node_opcua_assert_1.assert(node_opcua_status_code_1.StatusCodes.hasOwnProperty(statusCode.name));
/* istanbul ignore next*/
if (doDebug) {
debugLog(chalk.red(" Server aborting because ") + chalk.cyan(statusCode.name));
debugLog(chalk.red(" extraErrorDescription ") + chalk.cyan(extraErrorDescription));
}
const errorResponse = new TCPErrorMessage_1.TCPErrorMessage({
reason: statusCode.description,
statusCode,
});
const messageChunk = tools_1.packTcpMessage("ERR", errorResponse);
this.write(messageChunk);
this.disconnect(() => {
this._aborted = 2;
callback(new Error(extraErrorDescription + " StatusCode = " + statusCode.name));
});
}, ServerTCP_transport.throttleTime);
}
_abortWithError(statusCode, extraErrorDescription, callback) {
if (debugLog) {
debugLog(chalk.cyan("_abortWithError"));
else {
callback(new Error(statusCode.name));
}
}
_send_ACK_response(helloMessage) {
node_opcua_assert_1.assert(helloMessage.receiveBufferSize >= minimumBufferSize);
node_opcua_assert_1.assert(helloMessage.sendBufferSize >= minimumBufferSize);
this.receiveBufferSize = clamp_value(helloMessage.receiveBufferSize, 8192, 512 * 1024);
this.sendBufferSize = clamp_value(helloMessage.sendBufferSize, 8192, 512 * 1024);
this.maxMessageSize = clamp_value(helloMessage.maxMessageSize, 100000, 16 * 1024 * 1024);
this.maxChunkCount = clamp_value(helloMessage.maxChunkCount, 0, 65535);
const acknowledgeMessage = new AcknowledgeMessage_1.AcknowledgeMessage({
maxChunkCount: this.maxChunkCount,
maxMessageSize: this.maxMessageSize,
protocolVersion: this.protocolVersion,
receiveBufferSize: this.receiveBufferSize,
sendBufferSize: this.sendBufferSize,
});
const messageChunk = tools_1.packTcpMessage("ACK", acknowledgeMessage);
/* istanbul ignore next*/
if (doDebug) {
node_opcua_chunkmanager_1.verify_message_chunk(messageChunk);
debugLog("server send: " + chalk.yellow("ACK"));
debugLog("server send: " + hexDump(messageChunk));
debugLog("acknowledgeMessage=", acknowledgeMessage);
}
// send the ACK reply
this.write(messageChunk);
}
_install_HEL_message_receiver(callback) {
if (debugLog) {
debugLog(chalk.cyan("_install_HEL_message_receiver "));
}
this._install_one_time_message_receiver((err, data) => {
if (err) {
this._abortWithError(node_opcua_status_code_1.StatusCodes.BadConnectionRejected, err.message, callback);
}
node_opcua_assert_1.assert(_.isFunction(callback), "expecting a callback");
/* istanbul ignore else */
if (!this._aborted) {
setTimeout(() => {
this._aborted = 1;
// send the error message and close the connection
node_opcua_assert_1.assert(node_opcua_status_code_1.StatusCodes.hasOwnProperty(statusCode.name));
/* istanbul ignore next*/
if (doDebug) {
debugLog(chalk.red(" Server aborting because ") + chalk.cyan(statusCode.name));
debugLog(chalk.red(" extraErrorDescription ") + chalk.cyan(extraErrorDescription));
}
const errorResponse = new TCPErrorMessage_1.TCPErrorMessage({
reason: statusCode.description,
statusCode,
});
const messageChunk = tools_1.packTcpMessage("ERR", errorResponse);
this.write(messageChunk);
this.disconnect(() => {
this._aborted = 2;
callback(new Error(extraErrorDescription + " StatusCode = " + statusCode.name));
});
}, ServerTCP_transport.throttleTime);
}
else {
callback(new Error(statusCode.name));
if (!data) {
throw new Error("Invalid Data");
}
// handle the HEL message
this._on_HEL_message(data, callback);
}
});
}
_on_HEL_message(data, callback) {
if (debugLog) {
debugLog(chalk.cyan("_on_HEL_message"));
}
_send_ACK_response(helloMessage) {
node_opcua_assert_1.assert(helloMessage.receiveBufferSize >= minimumBufferSize);
node_opcua_assert_1.assert(helloMessage.sendBufferSize >= minimumBufferSize);
this.receiveBufferSize = clamp_value(helloMessage.receiveBufferSize, 8192, 512 * 1024);
this.sendBufferSize = clamp_value(helloMessage.sendBufferSize, 8192, 512 * 1024);
this.maxMessageSize = clamp_value(helloMessage.maxMessageSize, 100000, 16 * 1024 * 1024);
this.maxChunkCount = clamp_value(helloMessage.maxChunkCount, 0, 65535);
const acknowledgeMessage = new AcknowledgeMessage_1.AcknowledgeMessage({
maxChunkCount: this.maxChunkCount,
maxMessageSize: this.maxMessageSize,
protocolVersion: this.protocolVersion,
receiveBufferSize: this.receiveBufferSize,
sendBufferSize: this.sendBufferSize,
});
const messageChunk = tools_1.packTcpMessage("ACK", acknowledgeMessage);
/* istanbul ignore next*/
if (doDebug) {
node_opcua_chunkmanager_1.verify_message_chunk(messageChunk);
debugLog("server send: " + chalk.yellow("ACK"));
debugLog("server send: " + hexDump(messageChunk));
debugLog("acknowledgeMessage=", acknowledgeMessage);
}
// send the ACK reply
this.write(messageChunk);
node_opcua_assert_1.assert(data instanceof Buffer);
node_opcua_assert_1.assert(!this._helloReceived);
const stream = new node_opcua_binary_stream_1.BinaryStream(data);
const msgType = data.slice(0, 3).toString("ascii");
/* istanbul ignore next*/
if (doDebug) {
debugLog("SERVER received " + chalk.yellow(msgType));
debugLog("SERVER received " + hexDump(data));
}
_install_HEL_message_receiver(callback) {
if (debugLog) {
debugLog(chalk.cyan("_install_HEL_message_receiver "));
if (msgType === "HEL") {
node_opcua_assert_1.assert(data.length >= 24);
const helloMessage = tools_1.decodeMessage(stream, HelloMessage_1.HelloMessage);
node_opcua_assert_1.assert(_.isFinite(this.protocolVersion));
// OPCUA Spec 1.03 part 6 - page 41
// The Server shall always accept versions greater than what it supports.
if (helloMessage.protocolVersion !== this.protocolVersion) {
debugLog(`warning ! client sent helloMessage.protocolVersion = ` +
` 0x${helloMessage.protocolVersion.toString(16)} ` +
`whereas server protocolVersion is 0x${this.protocolVersion.toString(16)}`);
}
this._install_one_time_message_receiver((err, data) => {
if (err) {
this._abortWithError(node_opcua_status_code_1.StatusCodes.BadConnectionRejected, err.message, callback);
}
else {
if (!data) {
throw new Error("Invalid Data");
}
// handle the HEL message
this._on_HEL_message(data, callback);
}
});
if (helloMessage.protocolVersion === 0xdeadbeef || helloMessage.protocolVersion < this.protocolVersion) {
// Note: 0xDEADBEEF is our special version number to simulate BadProtocolVersionUnsupported in tests
// invalid protocol version requested by client
return this._abortWithError(node_opcua_status_code_1.StatusCodes.BadProtocolVersionUnsupported, "Protocol Version Error" + this.protocolVersion, callback);
}
// OPCUA Spec 1.04 part 6 - page 45
// UASC is designed to operate with different TransportProtocols that may have limited buffer
// sizes. For this reason, OPC UA Secure Conversation will break OPC UA Messages into several
// pieces (called ‘MessageChunks’) that are smaller than the buffer size allowed by the
// TransportProtocol. UASC requires a TransportProtocol buffer size that is at least 8 192 bytes
if (helloMessage.receiveBufferSize < minimumBufferSize || helloMessage.sendBufferSize < minimumBufferSize) {
return this._abortWithError(node_opcua_status_code_1.StatusCodes.BadConnectionRejected, "Buffer size too small (should be at least " + minimumBufferSize, callback);
}
// the helloMessage shall only be received once.
this._helloReceived = true;
this._send_ACK_response(helloMessage);
callback(); // no Error
}
_on_HEL_message(data, callback) {
if (debugLog) {
debugLog(chalk.cyan("_on_HEL_message"));
}
node_opcua_assert_1.assert(data instanceof Buffer);
node_opcua_assert_1.assert(!this._helloReceived);
const stream = new node_opcua_binary_stream_1.BinaryStream(data);
const msgType = data.slice(0, 3).toString("ascii");
else {
// invalid packet , expecting HEL
/* istanbul ignore next*/
if (doDebug) {
debugLog("SERVER received " + chalk.yellow(msgType));
debugLog("SERVER received " + hexDump(data));
debugLog(chalk.red("BadCommunicationError ") + "Expecting 'HEL' message to initiate communication");
}
if (msgType === "HEL") {
node_opcua_assert_1.assert(data.length >= 24);
const helloMessage = tools_1.decodeMessage(stream, HelloMessage_1.HelloMessage);
node_opcua_assert_1.assert(_.isFinite(this.protocolVersion));
// OPCUA Spec 1.03 part 6 - page 41
// The Server shall always accept versions greater than what it supports.
if (helloMessage.protocolVersion !== this.protocolVersion) {
debugLog(`warning ! client sent helloMessage.protocolVersion = ` +
` 0x${helloMessage.protocolVersion.toString(16)} ` +
`whereas server protocolVersion is 0x${this.protocolVersion.toString(16)}`);
}
if (helloMessage.protocolVersion === 0xdeadbeef || helloMessage.protocolVersion < this.protocolVersion) {
// Note: 0xDEADBEEF is our special version number to simulate BadProtocolVersionUnsupported in tests
// invalid protocol version requested by client
return this._abortWithError(node_opcua_status_code_1.StatusCodes.BadProtocolVersionUnsupported, "Protocol Version Error" + this.protocolVersion, callback);
}
// OPCUA Spec 1.04 part 6 - page 45
// UASC is designed to operate with different TransportProtocols that may have limited buffer
// sizes. For this reason, OPC UA Secure Conversation will break OPC UA Messages into several
// pieces (called ‘MessageChunks’) that are smaller than the buffer size allowed by the
// TransportProtocol. UASC requires a TransportProtocol buffer size that is at least 8 192 bytes
if (helloMessage.receiveBufferSize < minimumBufferSize || helloMessage.sendBufferSize < minimumBufferSize) {
return this._abortWithError(node_opcua_status_code_1.StatusCodes.BadConnectionRejected, "Buffer size too small (should be at least " + minimumBufferSize, callback);
}
// the helloMessage shall only be received once.
this._helloReceived = true;
this._send_ACK_response(helloMessage);
callback(); // no Error
}
else {
// invalid packet , expecting HEL
/* istanbul ignore next*/
if (doDebug) {
debugLog(chalk.red("BadCommunicationError ") + "Expecting 'HEL' message to initiate communication");
}
this._abortWithError(node_opcua_status_code_1.StatusCodes.BadCommunicationError, "Expecting 'HEL' message to initiate communication", callback);
}
this._abortWithError(node_opcua_status_code_1.StatusCodes.BadCommunicationError, "Expecting 'HEL' message to initiate communication", callback);
}
}
ServerTCP_transport.throttleTime = 1000;
return ServerTCP_transport;
})();
}
exports.ServerTCP_transport = ServerTCP_transport;
ServerTCP_transport.throttleTime = 1000;
//# sourceMappingURL=server_tcp_transport.js.map

@@ -33,323 +33,320 @@ "use strict";

// tslint:disable:class-name
let TCP_transport = /** @class */ (() => {
class TCP_transport extends events_1.EventEmitter {
constructor() {
super();
this.name = this.constructor.name + counter;
counter += 1;
this._timerId = null;
this._timeout = 30000; // 30 seconds timeout
class TCP_transport extends events_1.EventEmitter {
constructor() {
super();
this.name = this.constructor.name + counter;
counter += 1;
this._timerId = null;
this._timeout = 30000; // 30 seconds timeout
this._socket = null;
this.headerSize = 8;
this.protocolVersion = 0;
this._disconnecting = false;
this._pendingBuffer = undefined;
this.bytesWritten = 0;
this.bytesRead = 0;
this._theCallback = undefined;
this.chunkWrittenCount = 0;
this.chunkReadCount = 0;
this._onSocketClosedHasBeenCalled = false;
this._onSocketEndedHasBeenCalled = false;
TCP_transport.registry.register(this);
}
get timeout() {
return this._timeout;
}
set timeout(value) {
debugLog("Setting socket " + this.name + " timeout = ", value);
this._timeout = value;
}
dispose() {
this._cleanup_timers();
node_opcua_assert_1.assert(!this._timerId);
if (this._socket) {
this._socket.destroy();
this._socket.removeAllListeners();
this._socket = null;
this.headerSize = 8;
this.protocolVersion = 0;
this._disconnecting = false;
this._pendingBuffer = undefined;
this.bytesWritten = 0;
this.bytesRead = 0;
this._theCallback = undefined;
this.chunkWrittenCount = 0;
this.chunkReadCount = 0;
this._onSocketClosedHasBeenCalled = false;
this._onSocketEndedHasBeenCalled = false;
TCP_transport.registry.register(this);
}
get timeout() {
return this._timeout;
TCP_transport.registry.unregister(this);
}
/**
* ```createChunk``` is used to construct a pre-allocated chunk to store up to ```length``` bytes of data.
* The created chunk includes a prepended header for ```chunk_type``` of size ```self.headerSize```.
*
* @method createChunk
* @param msgType
* @param chunkType {String} chunk type. should be 'F' 'C' or 'A'
* @param length
* @return a buffer object with the required length representing the chunk.
*
* Note:
* - only one chunk can be created at a time.
* - a created chunk should be committed using the ```write``` method before an other one is created.
*/
createChunk(msgType, chunkType, length) {
node_opcua_assert_1.assert(msgType === "MSG");
node_opcua_assert_1.assert(this._pendingBuffer === undefined, "createChunk has already been called ( use write first)");
const totalLength = length + this.headerSize;
const buffer = node_opcua_buffer_utils_1.createFastUninitializedBuffer(totalLength);
tools_1.writeTCPMessageHeader("MSG", chunkType, totalLength, buffer);
this._pendingBuffer = buffer;
return buffer;
}
/**
* write the message_chunk on the socket.
* @method write
* @param messageChunk
*
* Notes:
* - the message chunk must have been created by ```createChunk```.
* - once a message chunk has been written, it is possible to call ```createChunk``` again.
*
*/
write(messageChunk) {
node_opcua_assert_1.assert((this._pendingBuffer === undefined)
|| this._pendingBuffer === messageChunk, " write should be used with buffer created by createChunk");
const header = message_builder_base_1.readRawMessageHeader(messageChunk);
node_opcua_assert_1.assert(header.length === messageChunk.length);
node_opcua_assert_1.assert(["F", "C", "A"].indexOf(header.messageHeader.isFinal) !== -1);
this._write_chunk(messageChunk);
this._pendingBuffer = undefined;
}
get isDisconnecting() {
return this._disconnecting;
}
/**
* disconnect the TCP layer and close the underlying socket.
* The ```"close"``` event will be emitted to the observers with err=null.
*
* @method disconnect
* @async
* @param callback
*/
disconnect(callback) {
node_opcua_assert_1.assert(_.isFunction(callback), "expecting a callback function, but got " + callback);
if (this._disconnecting) {
callback();
return;
}
set timeout(value) {
debugLog("Setting socket " + this.name + " timeout = ", value);
this._timeout = value;
node_opcua_assert_1.assert(!this._disconnecting, "TCP Transport has already been disconnected");
this._disconnecting = true;
// xx assert(!this._theCallback,
// "disconnect shall not be called while the 'one time message receiver' is in operation");
this._cleanup_timers();
if (this._socket) {
this._socket.end();
this._socket.destroy();
// xx this._socket.removeAllListeners();
this._socket = null;
}
dispose() {
this._cleanup_timers();
node_opcua_assert_1.assert(!this._timerId);
if (this._socket) {
this._socket.destroy();
this._socket.removeAllListeners();
this._socket = null;
}
TCP_transport.registry.unregister(this);
this.on_socket_ended(null);
setImmediate(() => {
callback();
});
}
isValid() {
return this._socket !== null && !this._socket.destroyed && !this._disconnecting;
}
_write_chunk(messageChunk) {
if (this._socket !== null) {
this.bytesWritten += messageChunk.length;
this.chunkWrittenCount++;
this._socket.write(messageChunk);
}
}
on_socket_ended(err) {
node_opcua_assert_1.assert(!this._onSocketEndedHasBeenCalled);
this._onSocketEndedHasBeenCalled = true; // we don't want to send close event twice ...
/**
* ```createChunk``` is used to construct a pre-allocated chunk to store up to ```length``` bytes of data.
* The created chunk includes a prepended header for ```chunk_type``` of size ```self.headerSize```.
*
* @method createChunk
* @param msgType
* @param chunkType {String} chunk type. should be 'F' 'C' or 'A'
* @param length
* @return a buffer object with the required length representing the chunk.
*
* Note:
* - only one chunk can be created at a time.
* - a created chunk should be committed using the ```write``` method before an other one is created.
* notify the observers that the transport layer has been disconnected.
* @event close
* @param err the Error object or null
*/
createChunk(msgType, chunkType, length) {
node_opcua_assert_1.assert(msgType === "MSG");
node_opcua_assert_1.assert(this._pendingBuffer === undefined, "createChunk has already been called ( use write first)");
const totalLength = length + this.headerSize;
const buffer = node_opcua_buffer_utils_1.createFastUninitializedBuffer(totalLength);
tools_1.writeTCPMessageHeader("MSG", chunkType, totalLength, buffer);
this._pendingBuffer = buffer;
return buffer;
this.emit("close", err || null);
}
/**
* @method _install_socket
* @param socket {Socket}
* @protected
*/
_install_socket(socket) {
node_opcua_assert_1.assert(socket);
this._socket = socket;
if (doDebug) {
debugLog("_install_socket ", this.name);
}
/**
* write the message_chunk on the socket.
* @method write
* @param messageChunk
*
* Notes:
* - the message chunk must have been created by ```createChunk```.
* - once a message chunk has been written, it is possible to call ```createChunk``` again.
*
*/
write(messageChunk) {
node_opcua_assert_1.assert((this._pendingBuffer === undefined)
|| this._pendingBuffer === messageChunk, " write should be used with buffer created by createChunk");
const header = message_builder_base_1.readRawMessageHeader(messageChunk);
node_opcua_assert_1.assert(header.length === messageChunk.length);
node_opcua_assert_1.assert(["F", "C", "A"].indexOf(header.messageHeader.isFinal) !== -1);
this._write_chunk(messageChunk);
this._pendingBuffer = undefined;
// install packet assembler ...
this.packetAssembler = new node_opcua_packet_assembler_1.PacketAssembler({
readMessageFunc: message_builder_base_1.readRawMessageHeader,
minimumSizeInBytes: this.headerSize
});
/* istanbul ignore next */
if (!this.packetAssembler) {
throw new Error("Internal Error");
}
get isDisconnecting() {
return this._disconnecting;
this.packetAssembler.on("message", (messageChunk) => this._on_message_received(messageChunk));
this._socket
.on("data", (data) => this._on_socket_data(data))
.on("close", (hadError) => this._on_socket_close(hadError))
.on("end", (err) => this._on_socket_end(err))
.on("error", (err) => this._on_socket_error(err));
// set socket timeout
debugLog("setting " + this.name + " _socket.setTimeout to ", this.timeout);
// let use a large timeout here to make sure that we not conflict with our internal timeout
this._socket.setTimeout(this.timeout + 2000, () => {
debugLog(` _socket ${this.name} has timed out (timeout = ${this.timeout})`);
this.prematureTerminate(new Error("INTERNAL_EPIPE timeout=" + this.timeout));
});
}
prematureTerminate(err) {
debugLog("prematureTerminate", err ? err.message : "");
if (this._socket) {
err.message = "EPIPE_" + err.message;
// we consider this as an error
const _s = this._socket;
_s.end();
_s.destroy(); // new Error("Socket has timed out"));
_s.emit("error", err);
this._socket = null;
this.dispose();
_s.removeAllListeners();
}
/**
* disconnect the TCP layer and close the underlying socket.
* The ```"close"``` event will be emitted to the observers with err=null.
*
* @method disconnect
* @async
* @param callback
*/
disconnect(callback) {
node_opcua_assert_1.assert(_.isFunction(callback), "expecting a callback function, but got " + callback);
if (this._disconnecting) {
callback();
return;
}
node_opcua_assert_1.assert(!this._disconnecting, "TCP Transport has already been disconnected");
this._disconnecting = true;
// xx assert(!this._theCallback,
// "disconnect shall not be called while the 'one time message receiver' is in operation");
this._cleanup_timers();
if (this._socket) {
this._socket.end();
this._socket.destroy();
// xx this._socket.removeAllListeners();
this._socket = null;
}
this.on_socket_ended(null);
setImmediate(() => {
callback();
});
}
/**
* @method _install_one_time_message_receiver
*
* install a one time message receiver callback
*
* Rules:
* * TCP_transport will not emit the ```message``` event, while the "one time message receiver" is in operation.
* * the TCP_transport will wait for the next complete message chunk and call the provided callback func
* ```callback(null,messageChunk);```
*
* if a messageChunk is not received within ```TCP_transport.timeout``` or if the underlying socket reports
* an error, the callback function will be called with an Error.
*
*/
_install_one_time_message_receiver(callback) {
node_opcua_assert_1.assert(!this._theCallback, "callback already set");
node_opcua_assert_1.assert(_.isFunction(callback));
this._theCallback = callback;
this._start_one_time_message_receiver();
}
_fulfill_pending_promises(err, data) {
this._cleanup_timers();
if (this._socket && this._on_error_during_one_time_message_receiver) {
this._socket.removeListener("close", this._on_error_during_one_time_message_receiver);
this._on_error_during_one_time_message_receiver = null;
}
isValid() {
return this._socket !== null && !this._socket.destroyed && !this._disconnecting;
const callback = this._theCallback;
this._theCallback = undefined;
if (callback) {
callback(err, data);
return true;
}
_write_chunk(messageChunk) {
if (this._socket !== null) {
this.bytesWritten += messageChunk.length;
this.chunkWrittenCount++;
this._socket.write(messageChunk);
}
}
on_socket_ended(err) {
node_opcua_assert_1.assert(!this._onSocketEndedHasBeenCalled);
this._onSocketEndedHasBeenCalled = true; // we don't want to send close event twice ...
return false;
}
_on_message_received(messageChunk) {
const hasCallback = this._fulfill_pending_promises(null, messageChunk);
this.chunkReadCount++;
if (!hasCallback) {
/**
* notify the observers that the transport layer has been disconnected.
* @event close
* @param err the Error object or null
* notify the observers that a message chunk has been received
* @event message
* @param message_chunk the message chunk
*/
this.emit("close", err || null);
this.emit("message", messageChunk);
}
/**
* @method _install_socket
* @param socket {Socket}
* @protected
*/
_install_socket(socket) {
node_opcua_assert_1.assert(socket);
this._socket = socket;
if (doDebug) {
debugLog("_install_socket ", this.name);
}
// install packet assembler ...
this.packetAssembler = new node_opcua_packet_assembler_1.PacketAssembler({
readMessageFunc: message_builder_base_1.readRawMessageHeader,
minimumSizeInBytes: this.headerSize
});
/* istanbul ignore next */
if (!this.packetAssembler) {
throw new Error("Internal Error");
}
this.packetAssembler.on("message", (messageChunk) => this._on_message_received(messageChunk));
this._socket
.on("data", (data) => this._on_socket_data(data))
.on("close", (hadError) => this._on_socket_close(hadError))
.on("end", (err) => this._on_socket_end(err))
.on("error", (err) => this._on_socket_error(err));
// set socket timeout
debugLog("setting " + this.name + " _socket.setTimeout to ", this.timeout);
// let use a large timeout here to make sure that we not conflict with our internal timeout
this._socket.setTimeout(this.timeout + 2000, () => {
debugLog(` _socket ${this.name} has timed out (timeout = ${this.timeout})`);
this.prematureTerminate(new Error("INTERNAL_EPIPE timeout=" + this.timeout));
});
}
_cleanup_timers() {
if (this._timerId) {
clearTimeout(this._timerId);
this._timerId = null;
}
prematureTerminate(err) {
debugLog("prematureTerminate", err ? err.message : "");
if (this._socket) {
err.message = "EPIPE_" + err.message;
// we consider this as an error
const _s = this._socket;
_s.end();
_s.destroy(); // new Error("Socket has timed out"));
_s.emit("error", err);
this._socket = null;
this.dispose();
_s.removeAllListeners();
}
}
_start_one_time_message_receiver() {
node_opcua_assert_1.assert(!this._timerId, "timer already started");
// Setup timeout detection timer ....
this._timerId = setTimeout(() => {
this._timerId = null;
this._fulfill_pending_promises(new Error(`Timeout in waiting for data on socket ( timeout was = ${this.timeout} ms)`));
}, this.timeout);
// also monitored
if (this._socket) {
// to do = intercept socket error as well
this._on_error_during_one_time_message_receiver = (err) => {
this._fulfill_pending_promises(new Error(`ERROR in waiting for data on socket ( timeout was = ${this.timeout} ms) ` + (err === null || err === void 0 ? void 0 : err.message)));
};
this._socket.on("close", this._on_error_during_one_time_message_receiver);
}
}
on_socket_closed(err) {
if (this._onSocketClosedHasBeenCalled) {
return;
}
node_opcua_assert_1.assert(!this._onSocketClosedHasBeenCalled);
this._onSocketClosedHasBeenCalled = true; // we don't want to send close event twice ...
/**
* @method _install_one_time_message_receiver
*
* install a one time message receiver callback
*
* Rules:
* * TCP_transport will not emit the ```message``` event, while the "one time message receiver" is in operation.
* * the TCP_transport will wait for the next complete message chunk and call the provided callback func
* ```callback(null,messageChunk);```
*
* if a messageChunk is not received within ```TCP_transport.timeout``` or if the underlying socket reports
* an error, the callback function will be called with an Error.
*
* notify the observers that the transport layer has been disconnected.
* @event socket_closed
* @param err the Error object or null
*/
_install_one_time_message_receiver(callback) {
node_opcua_assert_1.assert(!this._theCallback, "callback already set");
node_opcua_assert_1.assert(_.isFunction(callback));
this._theCallback = callback;
this._start_one_time_message_receiver();
this.emit("socket_closed", err || null);
}
_on_socket_data(data) {
if (!this.packetAssembler) {
throw new Error("internal Error");
}
_fulfill_pending_promises(err, data) {
this._cleanup_timers();
if (this._socket && this._on_error_during_one_time_message_receiver) {
this._socket.removeListener("close", this._on_error_during_one_time_message_receiver);
this._on_error_during_one_time_message_receiver = null;
}
const callback = this._theCallback;
this._theCallback = undefined;
if (callback) {
callback(err, data);
return true;
}
return false;
this.bytesRead += data.length;
if (data.length > 0) {
this.packetAssembler.feed(data);
}
_on_message_received(messageChunk) {
const hasCallback = this._fulfill_pending_promises(null, messageChunk);
this.chunkReadCount++;
if (!hasCallback) {
/**
* notify the observers that a message chunk has been received
* @event message
* @param message_chunk the message chunk
*/
this.emit("message", messageChunk);
}
}
_on_socket_close(hadError) {
// istanbul ignore next
if (doDebug) {
debugLog(chalk.red(" SOCKET CLOSE : "), chalk.yellow("had_error ="), chalk.cyan(hadError.toString()), this.name);
}
_cleanup_timers() {
if (this._timerId) {
clearTimeout(this._timerId);
this._timerId = null;
}
if (this._socket) {
debugLog(" remote address = ", this._socket.remoteAddress, " ", this._socket.remoteFamily, " ", this._socket.remotePort);
}
_start_one_time_message_receiver() {
node_opcua_assert_1.assert(!this._timerId, "timer already started");
// Setup timeout detection timer ....
this._timerId = setTimeout(() => {
this._timerId = null;
this._fulfill_pending_promises(new Error(`Timeout in waiting for data on socket ( timeout was = ${this.timeout} ms)`));
}, this.timeout);
// also monitored
if (hadError) {
if (this._socket) {
// to do = intercept socket error as well
this._on_error_during_one_time_message_receiver = (err) => {
this._fulfill_pending_promises(new Error(`ERROR in waiting for data on socket ( timeout was = ${this.timeout} ms) ` + (err === null || err === void 0 ? void 0 : err.message)));
};
this._socket.on("close", this._on_error_during_one_time_message_receiver);
this._socket.destroy();
}
}
on_socket_closed(err) {
if (this._onSocketClosedHasBeenCalled) {
return;
}
node_opcua_assert_1.assert(!this._onSocketClosedHasBeenCalled);
this._onSocketClosedHasBeenCalled = true; // we don't want to send close event twice ...
/**
* notify the observers that the transport layer has been disconnected.
* @event socket_closed
* @param err the Error object or null
*/
this.emit("socket_closed", err || null);
const err = hadError ? new Error("ERROR IN SOCKET " + hadError.toString()) : undefined;
this.on_socket_closed(err);
this.dispose();
}
_on_socket_ended_message(err) {
if (this._disconnecting) {
return;
}
_on_socket_data(data) {
if (!this.packetAssembler) {
throw new Error("internal Error");
}
this.bytesRead += data.length;
if (data.length > 0) {
this.packetAssembler.feed(data);
}
debugLog(chalk.red("Transport Connection ended") + " " + this.name);
node_opcua_assert_1.assert(!this._disconnecting);
err = err || new Error("_socket has been disconnected by third party");
this.on_socket_ended(err);
this._disconnecting = true;
debugLog(" bytesRead = ", this.bytesRead);
debugLog(" bytesWritten = ", this.bytesWritten);
this._fulfill_pending_promises(new Error("Connection aborted - ended by server : " + (err ? err.message : "")));
}
_on_socket_end(err) {
// istanbul ignore next
if (doDebug) {
debugLog(chalk.red(" SOCKET END : err="), chalk.yellow(err ? err.message : "null"), this.name);
}
_on_socket_close(hadError) {
// istanbul ignore next
if (doDebug) {
debugLog(chalk.red(" SOCKET CLOSE : "), chalk.yellow("had_error ="), chalk.cyan(hadError.toString()), this.name);
}
if (this._socket) {
debugLog(" remote address = ", this._socket.remoteAddress, " ", this._socket.remoteFamily, " ", this._socket.remotePort);
}
if (hadError) {
if (this._socket) {
this._socket.destroy();
}
}
const err = hadError ? new Error("ERROR IN SOCKET " + hadError.toString()) : undefined;
this.on_socket_closed(err);
this.dispose();
this._on_socket_ended_message(err);
}
_on_socket_error(err) {
// istanbul ignore next
if (doDebug) {
debugLog(chalk.red(" SOCKET ERROR : "), chalk.yellow(err.message), this.name);
}
_on_socket_ended_message(err) {
if (this._disconnecting) {
return;
}
debugLog(chalk.red("Transport Connection ended") + " " + this.name);
node_opcua_assert_1.assert(!this._disconnecting);
err = err || new Error("_socket has been disconnected by third party");
this.on_socket_ended(err);
this._disconnecting = true;
debugLog(" bytesRead = ", this.bytesRead);
debugLog(" bytesWritten = ", this.bytesWritten);
this._fulfill_pending_promises(new Error("Connection aborted - ended by server : " + (err ? err.message : "")));
}
_on_socket_end(err) {
// istanbul ignore next
if (doDebug) {
debugLog(chalk.red(" SOCKET END : err="), chalk.yellow(err ? err.message : "null"), this.name);
}
this._on_socket_ended_message(err);
}
_on_socket_error(err) {
// istanbul ignore next
if (doDebug) {
debugLog(chalk.red(" SOCKET ERROR : "), chalk.yellow(err.message), this.name);
}
// node The "close" event will be called directly following this event.
}
// node The "close" event will be called directly following this event.
}
TCP_transport.registry = new node_opcua_object_registry_1.ObjectRegistry();
return TCP_transport;
})();
}
exports.TCP_transport = TCP_transport;
TCP_transport.registry = new node_opcua_object_registry_1.ObjectRegistry();
//# sourceMappingURL=tcp_transport.js.map

@@ -20,32 +20,29 @@ "use strict";

});
let TCPErrorMessage = /** @class */ (() => {
class TCPErrorMessage extends node_opcua_factory_1.BaseUAObject {
constructor(options) {
options = options || {};
const schema = schemaTCPErrorMessage;
super();
/* istanbul ignore next */
if (node_opcua_factory_1.parameters.debugSchemaHelper) {
node_opcua_factory_1.check_options_correctness_against_schema(this, schema, options);
}
this.statusCode = node_opcua_factory_1.initialize_field(schema.fields[0], options.statusCode);
this.reason = node_opcua_factory_1.initialize_field(schema.fields[1], options.reason);
class TCPErrorMessage extends node_opcua_factory_1.BaseUAObject {
constructor(options) {
options = options || {};
const schema = schemaTCPErrorMessage;
super();
/* istanbul ignore next */
if (node_opcua_factory_1.parameters.debugSchemaHelper) {
node_opcua_factory_1.check_options_correctness_against_schema(this, schema, options);
}
encode(stream) {
// call base class implementation first
super.encode(stream);
node_opcua_status_code_1.encodeStatusCode(this.statusCode, stream);
node_opcua_basic_types_1.encodeString(this.reason, stream);
}
decode(stream) {
// call base class implementation first
super.decode(stream);
this.statusCode = node_opcua_status_code_1.decodeStatusCode(stream);
this.reason = node_opcua_basic_types_1.decodeString(stream);
}
this.statusCode = node_opcua_factory_1.initialize_field(schema.fields[0], options.statusCode);
this.reason = node_opcua_factory_1.initialize_field(schema.fields[1], options.reason);
}
TCPErrorMessage.possibleFields = ["statusCode", "reason"];
return TCPErrorMessage;
})();
encode(stream) {
// call base class implementation first
super.encode(stream);
node_opcua_status_code_1.encodeStatusCode(this.statusCode, stream);
node_opcua_basic_types_1.encodeString(this.reason, stream);
}
decode(stream) {
// call base class implementation first
super.decode(stream);
this.statusCode = node_opcua_status_code_1.decodeStatusCode(stream);
this.reason = node_opcua_basic_types_1.decodeString(stream);
}
}
exports.TCPErrorMessage = TCPErrorMessage;
TCPErrorMessage.possibleFields = ["statusCode", "reason"];
//# sourceMappingURL=TCPErrorMessage.js.map
{
"name": "node-opcua-transport",
"version": "2.13.0",
"version": "2.15.0",
"description": "pure nodejs OPCUA SDK - module -transport",

@@ -25,3 +25,3 @@ "main": "./dist/source/index.js",

"node-opcua-status-code": "2.11.0",
"node-opcua-types": "2.13.0",
"node-opcua-types": "2.15.0",
"node-opcua-utils": "2.13.0",

@@ -35,3 +35,3 @@ "underscore": "^1.10.2"

"node-opcua-debug": "2.8.1",
"node-opcua-generator": "2.13.0",
"node-opcua-generator": "2.15.0",
"should": "^13.2.3",

@@ -55,3 +55,3 @@ "sinon": "^9.0.2"

"homepage": "http://node-opcua.github.io/",
"gitHead": "3c8a33e1e9d7923c9434607ad22d51d6d8d58918"
"gitHead": "d92ce0bdee1ed90c2b38ee20420f091fe9bf7365"
}

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc