node-opcua-transport
Advanced tools
Comparing version 2.13.0 to 2.15.0
@@ -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
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
241147
4015
+ Addednode-opcua-data-value@2.15.0(transitive)
+ Addednode-opcua-generator@2.15.0(transitive)
+ Addednode-opcua-schemas@2.15.0(transitive)
+ Addednode-opcua-types@2.15.0(transitive)
+ Addednode-opcua-variant@2.15.0(transitive)
+ Addednode-opcua-xml2json@2.15.0(transitive)
- Removednode-opcua-data-value@2.13.0(transitive)
- Removednode-opcua-generator@2.13.0(transitive)
- Removednode-opcua-schemas@2.13.0(transitive)
- Removednode-opcua-types@2.13.0(transitive)
- Removednode-opcua-variant@2.13.0(transitive)
- Removednode-opcua-xml2json@2.13.0(transitive)
Updatednode-opcua-types@2.15.0