node-opcua-transport 2.64.1 → 2.65.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/source/AcknowledgeMessage.d.ts +27 -27
- package/dist/source/AcknowledgeMessage.js +78 -78
- package/dist/source/HelloMessage.d.ts +27 -27
- package/dist/source/HelloMessage.js +94 -94
- package/dist/source/TCPErrorMessage.d.ts +18 -18
- package/dist/source/TCPErrorMessage.js +46 -46
- package/dist/source/client_tcp_transport.d.ts +68 -68
- package/dist/source/client_tcp_transport.js +313 -313
- package/dist/source/index.d.ts +11 -11
- package/dist/source/index.js +23 -23
- package/dist/source/message_builder_base.d.ts +61 -61
- package/dist/source/message_builder_base.js +206 -206
- package/dist/source/server_tcp_transport.d.ts +48 -48
- package/dist/source/server_tcp_transport.js +226 -226
- package/dist/source/tcp_transport.d.ts +126 -126
- package/dist/source/tcp_transport.js +357 -357
- package/dist/source/tools.d.ts +13 -13
- package/dist/source/tools.js +103 -103
- package/dist/source/utils.d.ts +2 -2
- package/dist/source/utils.js +8 -8
- package/dist/test-fixtures/fixture_full_tcp_packets.d.ts +21 -21
- package/dist/test-fixtures/fixture_full_tcp_packets.js +41 -41
- package/dist/test-fixtures/index.d.ts +1 -1
- package/dist/test-fixtures/index.js +13 -13
- package/dist/test_helpers/direct_transport.d.ts +14 -14
- package/dist/test_helpers/direct_transport.js +62 -62
- package/dist/test_helpers/fake_server.d.ts +17 -17
- package/dist/test_helpers/fake_server.js +54 -54
- package/dist/test_helpers/half_com_channel.d.ts +10 -10
- package/dist/test_helpers/half_com_channel.js +31 -31
- package/dist/test_helpers/index.d.ts +4 -4
- package/dist/test_helpers/index.js +16 -16
- package/dist/test_helpers/socket_transport.d.ts +10 -10
- package/dist/test_helpers/socket_transport.js +30 -30
- package/package.json +4 -4
package/dist/source/index.js
CHANGED
|
@@ -1,24 +1,24 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
-
if (k2 === undefined) k2 = k;
|
|
4
|
-
Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
|
|
5
|
-
}) : (function(o, m, k, k2) {
|
|
6
|
-
if (k2 === undefined) k2 = k;
|
|
7
|
-
o[k2] = m[k];
|
|
8
|
-
}));
|
|
9
|
-
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
10
|
-
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
11
|
-
};
|
|
12
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
13
|
-
/**
|
|
14
|
-
* @module node-opcua-transport
|
|
15
|
-
*/
|
|
16
|
-
__exportStar(require("./HelloMessage"), exports);
|
|
17
|
-
__exportStar(require("./AcknowledgeMessage"), exports);
|
|
18
|
-
__exportStar(require("./TCPErrorMessage"), exports);
|
|
19
|
-
__exportStar(require("./client_tcp_transport"), exports);
|
|
20
|
-
__exportStar(require("./server_tcp_transport"), exports);
|
|
21
|
-
__exportStar(require("./tcp_transport"), exports);
|
|
22
|
-
__exportStar(require("./tools"), exports);
|
|
23
|
-
__exportStar(require("./message_builder_base"), exports);
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
|
|
5
|
+
}) : (function(o, m, k, k2) {
|
|
6
|
+
if (k2 === undefined) k2 = k;
|
|
7
|
+
o[k2] = m[k];
|
|
8
|
+
}));
|
|
9
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
10
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
11
|
+
};
|
|
12
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
13
|
+
/**
|
|
14
|
+
* @module node-opcua-transport
|
|
15
|
+
*/
|
|
16
|
+
__exportStar(require("./HelloMessage"), exports);
|
|
17
|
+
__exportStar(require("./AcknowledgeMessage"), exports);
|
|
18
|
+
__exportStar(require("./TCPErrorMessage"), exports);
|
|
19
|
+
__exportStar(require("./client_tcp_transport"), exports);
|
|
20
|
+
__exportStar(require("./server_tcp_transport"), exports);
|
|
21
|
+
__exportStar(require("./tcp_transport"), exports);
|
|
22
|
+
__exportStar(require("./tools"), exports);
|
|
23
|
+
__exportStar(require("./message_builder_base"), exports);
|
|
24
24
|
//# sourceMappingURL=index.js.map
|
|
@@ -1,61 +1,61 @@
|
|
|
1
|
-
/// <reference types="node" />
|
|
2
|
-
/**
|
|
3
|
-
* @module node-opcua-transport
|
|
4
|
-
*/
|
|
5
|
-
import { EventEmitter } from "events";
|
|
6
|
-
import { BinaryStream } from "node-opcua-binary-stream";
|
|
7
|
-
import { SequenceHeader } from "node-opcua-chunkmanager";
|
|
8
|
-
import { MessageHeader, PacketAssembler, PacketInfo } from "node-opcua-packet-assembler";
|
|
9
|
-
export declare function readRawMessageHeader(data: Buffer): PacketInfo;
|
|
10
|
-
/**
|
|
11
|
-
* @class MessageBuilderBase
|
|
12
|
-
* @extends EventEmitter
|
|
13
|
-
* @uses PacketAssembler
|
|
14
|
-
* @constructor
|
|
15
|
-
* @param options {Object}
|
|
16
|
-
* @param [options.signatureLength=0] {number}
|
|
17
|
-
*
|
|
18
|
-
*/
|
|
19
|
-
export declare class MessageBuilderBase extends EventEmitter {
|
|
20
|
-
readonly signatureLength: number;
|
|
21
|
-
readonly options: {
|
|
22
|
-
signatureLength?: number;
|
|
23
|
-
};
|
|
24
|
-
readonly _packetAssembler: PacketAssembler;
|
|
25
|
-
channelId: number;
|
|
26
|
-
totalMessageSize: number;
|
|
27
|
-
sequenceHeader: SequenceHeader | null;
|
|
28
|
-
_tick0: number;
|
|
29
|
-
_tick1: number;
|
|
30
|
-
protected id: string;
|
|
31
|
-
protected totalBodySize: number;
|
|
32
|
-
protected messageChunks: Buffer[];
|
|
33
|
-
protected messageHeader?: MessageHeader;
|
|
34
|
-
private _securityDefeated;
|
|
35
|
-
private _hasReceivedError;
|
|
36
|
-
private blocks;
|
|
37
|
-
private readonly _expectedChannelId;
|
|
38
|
-
private offsetBodyStart;
|
|
39
|
-
constructor(options?: {
|
|
40
|
-
signatureLength?: number;
|
|
41
|
-
});
|
|
42
|
-
dispose(): void;
|
|
43
|
-
/**
|
|
44
|
-
* Feed message builder with some data
|
|
45
|
-
* @method feed
|
|
46
|
-
* @param data
|
|
47
|
-
*/
|
|
48
|
-
feed(data: Buffer): void;
|
|
49
|
-
protected _decodeMessageBody(fullMessageBody: Buffer): boolean;
|
|
50
|
-
protected _read_headers(binaryStream: BinaryStream): boolean;
|
|
51
|
-
protected _report_error(errorMessage: string): false;
|
|
52
|
-
private _init_new;
|
|
53
|
-
/**
|
|
54
|
-
* append a message chunk
|
|
55
|
-
* @method _append
|
|
56
|
-
* @param chunk
|
|
57
|
-
* @private
|
|
58
|
-
*/
|
|
59
|
-
private _append;
|
|
60
|
-
private _feed_messageChunk;
|
|
61
|
-
}
|
|
1
|
+
/// <reference types="node" />
|
|
2
|
+
/**
|
|
3
|
+
* @module node-opcua-transport
|
|
4
|
+
*/
|
|
5
|
+
import { EventEmitter } from "events";
|
|
6
|
+
import { BinaryStream } from "node-opcua-binary-stream";
|
|
7
|
+
import { SequenceHeader } from "node-opcua-chunkmanager";
|
|
8
|
+
import { MessageHeader, PacketAssembler, PacketInfo } from "node-opcua-packet-assembler";
|
|
9
|
+
export declare function readRawMessageHeader(data: Buffer): PacketInfo;
|
|
10
|
+
/**
|
|
11
|
+
* @class MessageBuilderBase
|
|
12
|
+
* @extends EventEmitter
|
|
13
|
+
* @uses PacketAssembler
|
|
14
|
+
* @constructor
|
|
15
|
+
* @param options {Object}
|
|
16
|
+
* @param [options.signatureLength=0] {number}
|
|
17
|
+
*
|
|
18
|
+
*/
|
|
19
|
+
export declare class MessageBuilderBase extends EventEmitter {
|
|
20
|
+
readonly signatureLength: number;
|
|
21
|
+
readonly options: {
|
|
22
|
+
signatureLength?: number;
|
|
23
|
+
};
|
|
24
|
+
readonly _packetAssembler: PacketAssembler;
|
|
25
|
+
channelId: number;
|
|
26
|
+
totalMessageSize: number;
|
|
27
|
+
sequenceHeader: SequenceHeader | null;
|
|
28
|
+
_tick0: number;
|
|
29
|
+
_tick1: number;
|
|
30
|
+
protected id: string;
|
|
31
|
+
protected totalBodySize: number;
|
|
32
|
+
protected messageChunks: Buffer[];
|
|
33
|
+
protected messageHeader?: MessageHeader;
|
|
34
|
+
private _securityDefeated;
|
|
35
|
+
private _hasReceivedError;
|
|
36
|
+
private blocks;
|
|
37
|
+
private readonly _expectedChannelId;
|
|
38
|
+
private offsetBodyStart;
|
|
39
|
+
constructor(options?: {
|
|
40
|
+
signatureLength?: number;
|
|
41
|
+
});
|
|
42
|
+
dispose(): void;
|
|
43
|
+
/**
|
|
44
|
+
* Feed message builder with some data
|
|
45
|
+
* @method feed
|
|
46
|
+
* @param data
|
|
47
|
+
*/
|
|
48
|
+
feed(data: Buffer): void;
|
|
49
|
+
protected _decodeMessageBody(fullMessageBody: Buffer): boolean;
|
|
50
|
+
protected _read_headers(binaryStream: BinaryStream): boolean;
|
|
51
|
+
protected _report_error(errorMessage: string): false;
|
|
52
|
+
private _init_new;
|
|
53
|
+
/**
|
|
54
|
+
* append a message chunk
|
|
55
|
+
* @method _append
|
|
56
|
+
* @param chunk
|
|
57
|
+
* @private
|
|
58
|
+
*/
|
|
59
|
+
private _append;
|
|
60
|
+
private _feed_messageChunk;
|
|
61
|
+
}
|
|
@@ -1,207 +1,207 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.MessageBuilderBase = exports.readRawMessageHeader = void 0;
|
|
4
|
-
/**
|
|
5
|
-
* @module node-opcua-transport
|
|
6
|
-
*/
|
|
7
|
-
const events_1 = require("events");
|
|
8
|
-
const node_opcua_assert_1 = require("node-opcua-assert");
|
|
9
|
-
const node_opcua_binary_stream_1 = require("node-opcua-binary-stream");
|
|
10
|
-
const node_opcua_buffer_utils_1 = require("node-opcua-buffer-utils");
|
|
11
|
-
const node_opcua_chunkmanager_1 = require("node-opcua-chunkmanager");
|
|
12
|
-
const node_opcua_debug_1 = require("node-opcua-debug");
|
|
13
|
-
const node_opcua_packet_assembler_1 = require("node-opcua-packet-assembler");
|
|
14
|
-
const node_opcua_utils_1 = require("node-opcua-utils");
|
|
15
|
-
const doPerfMonitoring = process.env.NODEOPCUADEBUG && process.env.NODEOPCUADEBUG.indexOf("PERF") >= 0;
|
|
16
|
-
const errorLog = (0, node_opcua_debug_1.make_errorLog)("MessageBuilder");
|
|
17
|
-
const debugLog = (0, node_opcua_debug_1.make_debugLog)("MessageBuilder");
|
|
18
|
-
function readRawMessageHeader(data) {
|
|
19
|
-
const messageHeader = (0, node_opcua_chunkmanager_1.readMessageHeader)(new node_opcua_binary_stream_1.BinaryStream(data));
|
|
20
|
-
return {
|
|
21
|
-
extra: "",
|
|
22
|
-
length: messageHeader.length,
|
|
23
|
-
messageHeader
|
|
24
|
-
};
|
|
25
|
-
}
|
|
26
|
-
exports.readRawMessageHeader = readRawMessageHeader;
|
|
27
|
-
/**
|
|
28
|
-
* @class MessageBuilderBase
|
|
29
|
-
* @extends EventEmitter
|
|
30
|
-
* @uses PacketAssembler
|
|
31
|
-
* @constructor
|
|
32
|
-
* @param options {Object}
|
|
33
|
-
* @param [options.signatureLength=0] {number}
|
|
34
|
-
*
|
|
35
|
-
*/
|
|
36
|
-
class MessageBuilderBase extends events_1.EventEmitter {
|
|
37
|
-
constructor(options) {
|
|
38
|
-
super();
|
|
39
|
-
this.id = "";
|
|
40
|
-
this._tick0 = 0;
|
|
41
|
-
this._tick1 = 0;
|
|
42
|
-
this._hasReceivedError = false;
|
|
43
|
-
this.blocks = [];
|
|
44
|
-
this.messageChunks = [];
|
|
45
|
-
this._expectedChannelId = 0;
|
|
46
|
-
options = options || {};
|
|
47
|
-
this.signatureLength = options.signatureLength || 0;
|
|
48
|
-
this.options = options;
|
|
49
|
-
this._packetAssembler = new node_opcua_packet_assembler_1.PacketAssembler({
|
|
50
|
-
minimumSizeInBytes: 0,
|
|
51
|
-
readMessageFunc: readRawMessageHeader
|
|
52
|
-
});
|
|
53
|
-
this._packetAssembler.on("message", (messageChunk) => this._feed_messageChunk(messageChunk));
|
|
54
|
-
this._packetAssembler.on("newMessage", (info, data) => {
|
|
55
|
-
if (doPerfMonitoring) {
|
|
56
|
-
// record tick 0: when the first data is received
|
|
57
|
-
this._tick0 = (0, node_opcua_utils_1.get_clock_tick)();
|
|
58
|
-
}
|
|
59
|
-
/**
|
|
60
|
-
*
|
|
61
|
-
* notify the observers that a new message is being built
|
|
62
|
-
* @event start_chunk
|
|
63
|
-
* @param info
|
|
64
|
-
* @param data
|
|
65
|
-
*/
|
|
66
|
-
this.emit("start_chunk", info, data);
|
|
67
|
-
});
|
|
68
|
-
this._securityDefeated = false;
|
|
69
|
-
this.totalBodySize = 0;
|
|
70
|
-
this.totalMessageSize = 0;
|
|
71
|
-
this.channelId = 0;
|
|
72
|
-
this.offsetBodyStart = 0;
|
|
73
|
-
this.sequenceHeader = null;
|
|
74
|
-
this._init_new();
|
|
75
|
-
}
|
|
76
|
-
dispose() {
|
|
77
|
-
this.removeAllListeners();
|
|
78
|
-
}
|
|
79
|
-
/**
|
|
80
|
-
* Feed message builder with some data
|
|
81
|
-
* @method feed
|
|
82
|
-
* @param data
|
|
83
|
-
*/
|
|
84
|
-
feed(data) {
|
|
85
|
-
if (!this._securityDefeated && !this._hasReceivedError) {
|
|
86
|
-
this._packetAssembler.feed(data);
|
|
87
|
-
}
|
|
88
|
-
}
|
|
89
|
-
_decodeMessageBody(fullMessageBody) {
|
|
90
|
-
return true;
|
|
91
|
-
}
|
|
92
|
-
_read_headers(binaryStream) {
|
|
93
|
-
try {
|
|
94
|
-
this.messageHeader = (0, node_opcua_chunkmanager_1.readMessageHeader)(binaryStream);
|
|
95
|
-
(0, node_opcua_assert_1.assert)(binaryStream.length === 8, "expecting message header to be 8 bytes");
|
|
96
|
-
this.channelId = binaryStream.readUInt32();
|
|
97
|
-
(0, node_opcua_assert_1.assert)(binaryStream.length === 12);
|
|
98
|
-
// verifying secure ChannelId
|
|
99
|
-
if (this._expectedChannelId && this.channelId !== this._expectedChannelId) {
|
|
100
|
-
return this._report_error("Invalid secure channel Id");
|
|
101
|
-
}
|
|
102
|
-
return true;
|
|
103
|
-
}
|
|
104
|
-
catch (err) {
|
|
105
|
-
return false;
|
|
106
|
-
}
|
|
107
|
-
}
|
|
108
|
-
_report_error(errorMessage) {
|
|
109
|
-
this._hasReceivedError = true;
|
|
110
|
-
/**
|
|
111
|
-
* notify the observers that an error has occurred
|
|
112
|
-
* @event error
|
|
113
|
-
* @param error the error to raise
|
|
114
|
-
*/
|
|
115
|
-
debugLog("Error ", this.id, errorMessage);
|
|
116
|
-
// xx errorLog(new Error());
|
|
117
|
-
this.emit("error", new Error(errorMessage), this.sequenceHeader ? this.sequenceHeader.requestId : null);
|
|
118
|
-
return false;
|
|
119
|
-
}
|
|
120
|
-
_init_new() {
|
|
121
|
-
this._securityDefeated = false;
|
|
122
|
-
this._hasReceivedError = false;
|
|
123
|
-
this.totalBodySize = 0;
|
|
124
|
-
this.totalMessageSize = 0;
|
|
125
|
-
this.blocks = [];
|
|
126
|
-
this.messageChunks = [];
|
|
127
|
-
}
|
|
128
|
-
/**
|
|
129
|
-
* append a message chunk
|
|
130
|
-
* @method _append
|
|
131
|
-
* @param chunk
|
|
132
|
-
* @private
|
|
133
|
-
*/
|
|
134
|
-
_append(chunk) {
|
|
135
|
-
if (this._hasReceivedError) {
|
|
136
|
-
// the message builder is in error mode and further message chunks should be discarded.
|
|
137
|
-
return false;
|
|
138
|
-
}
|
|
139
|
-
this.messageChunks.push(chunk);
|
|
140
|
-
this.totalMessageSize += chunk.length;
|
|
141
|
-
const binaryStream = new node_opcua_binary_stream_1.BinaryStream(chunk);
|
|
142
|
-
if (!this._read_headers(binaryStream)) {
|
|
143
|
-
return this._report_error(`Invalid message header detected`);
|
|
144
|
-
}
|
|
145
|
-
(0, node_opcua_assert_1.assert)(binaryStream.length >= 12);
|
|
146
|
-
// verify message chunk length
|
|
147
|
-
if (this.messageHeader.length !== chunk.length) {
|
|
148
|
-
// tslint:disable:max-line-length
|
|
149
|
-
return this._report_error(`Invalid messageChunk size: the provided chunk is ${chunk.length} bytes long but header specifies ${this.messageHeader.length}`);
|
|
150
|
-
}
|
|
151
|
-
// the start of the message body block
|
|
152
|
-
const offsetBodyStart = binaryStream.length;
|
|
153
|
-
// the end of the message body block
|
|
154
|
-
const offsetBodyEnd = binaryStream.buffer.length;
|
|
155
|
-
this.totalBodySize += offsetBodyEnd - offsetBodyStart;
|
|
156
|
-
this.offsetBodyStart = offsetBodyStart;
|
|
157
|
-
// add message body to a queue
|
|
158
|
-
// note : Buffer.slice create a shared memory !
|
|
159
|
-
// use Buffer.clone
|
|
160
|
-
const sharedBuffer = chunk.slice(this.offsetBodyStart, offsetBodyEnd);
|
|
161
|
-
const clonedBuffer = (0, node_opcua_buffer_utils_1.createFastUninitializedBuffer)(sharedBuffer.length);
|
|
162
|
-
sharedBuffer.copy(clonedBuffer, 0, 0);
|
|
163
|
-
this.blocks.push(clonedBuffer);
|
|
164
|
-
return true;
|
|
165
|
-
}
|
|
166
|
-
_feed_messageChunk(chunk) {
|
|
167
|
-
(0, node_opcua_assert_1.assert)(chunk);
|
|
168
|
-
const messageHeader = (0, node_opcua_chunkmanager_1.readMessageHeader)(new node_opcua_binary_stream_1.BinaryStream(chunk));
|
|
169
|
-
/**
|
|
170
|
-
* notify the observers that new message chunk has been received
|
|
171
|
-
* @event chunk
|
|
172
|
-
* @param messageChunk the raw message chunk
|
|
173
|
-
*/
|
|
174
|
-
this.emit("chunk", chunk);
|
|
175
|
-
if (messageHeader.isFinal === "F") {
|
|
176
|
-
// last message
|
|
177
|
-
this._append(chunk);
|
|
178
|
-
if (this._hasReceivedError) {
|
|
179
|
-
return false;
|
|
180
|
-
}
|
|
181
|
-
const fullMessageBody = this.blocks.length === 1 ? this.blocks[0] : Buffer.concat(this.blocks);
|
|
182
|
-
if (doPerfMonitoring) {
|
|
183
|
-
// record tick 1: when a complete message has been received ( all chunks assembled)
|
|
184
|
-
this._tick1 = (0, node_opcua_utils_1.get_clock_tick)();
|
|
185
|
-
}
|
|
186
|
-
/**
|
|
187
|
-
* notify the observers that a full message has been received
|
|
188
|
-
* @event full_message_body
|
|
189
|
-
* @param full_message_body the full message body made of all concatenated chunks.
|
|
190
|
-
*/
|
|
191
|
-
this.emit("full_message_body", fullMessageBody);
|
|
192
|
-
this._decodeMessageBody(fullMessageBody);
|
|
193
|
-
// be ready for next block
|
|
194
|
-
this._init_new();
|
|
195
|
-
return true;
|
|
196
|
-
}
|
|
197
|
-
else if (messageHeader.isFinal === "A") {
|
|
198
|
-
return this._report_error("received and Abort Message");
|
|
199
|
-
}
|
|
200
|
-
else if (messageHeader.isFinal === "C") {
|
|
201
|
-
return this._append(chunk);
|
|
202
|
-
}
|
|
203
|
-
return false;
|
|
204
|
-
}
|
|
205
|
-
}
|
|
206
|
-
exports.MessageBuilderBase = MessageBuilderBase;
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.MessageBuilderBase = exports.readRawMessageHeader = void 0;
|
|
4
|
+
/**
|
|
5
|
+
* @module node-opcua-transport
|
|
6
|
+
*/
|
|
7
|
+
const events_1 = require("events");
|
|
8
|
+
const node_opcua_assert_1 = require("node-opcua-assert");
|
|
9
|
+
const node_opcua_binary_stream_1 = require("node-opcua-binary-stream");
|
|
10
|
+
const node_opcua_buffer_utils_1 = require("node-opcua-buffer-utils");
|
|
11
|
+
const node_opcua_chunkmanager_1 = require("node-opcua-chunkmanager");
|
|
12
|
+
const node_opcua_debug_1 = require("node-opcua-debug");
|
|
13
|
+
const node_opcua_packet_assembler_1 = require("node-opcua-packet-assembler");
|
|
14
|
+
const node_opcua_utils_1 = require("node-opcua-utils");
|
|
15
|
+
const doPerfMonitoring = process.env.NODEOPCUADEBUG && process.env.NODEOPCUADEBUG.indexOf("PERF") >= 0;
|
|
16
|
+
const errorLog = (0, node_opcua_debug_1.make_errorLog)("MessageBuilder");
|
|
17
|
+
const debugLog = (0, node_opcua_debug_1.make_debugLog)("MessageBuilder");
|
|
18
|
+
function readRawMessageHeader(data) {
|
|
19
|
+
const messageHeader = (0, node_opcua_chunkmanager_1.readMessageHeader)(new node_opcua_binary_stream_1.BinaryStream(data));
|
|
20
|
+
return {
|
|
21
|
+
extra: "",
|
|
22
|
+
length: messageHeader.length,
|
|
23
|
+
messageHeader
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
exports.readRawMessageHeader = readRawMessageHeader;
|
|
27
|
+
/**
|
|
28
|
+
* @class MessageBuilderBase
|
|
29
|
+
* @extends EventEmitter
|
|
30
|
+
* @uses PacketAssembler
|
|
31
|
+
* @constructor
|
|
32
|
+
* @param options {Object}
|
|
33
|
+
* @param [options.signatureLength=0] {number}
|
|
34
|
+
*
|
|
35
|
+
*/
|
|
36
|
+
class MessageBuilderBase extends events_1.EventEmitter {
|
|
37
|
+
constructor(options) {
|
|
38
|
+
super();
|
|
39
|
+
this.id = "";
|
|
40
|
+
this._tick0 = 0;
|
|
41
|
+
this._tick1 = 0;
|
|
42
|
+
this._hasReceivedError = false;
|
|
43
|
+
this.blocks = [];
|
|
44
|
+
this.messageChunks = [];
|
|
45
|
+
this._expectedChannelId = 0;
|
|
46
|
+
options = options || {};
|
|
47
|
+
this.signatureLength = options.signatureLength || 0;
|
|
48
|
+
this.options = options;
|
|
49
|
+
this._packetAssembler = new node_opcua_packet_assembler_1.PacketAssembler({
|
|
50
|
+
minimumSizeInBytes: 0,
|
|
51
|
+
readMessageFunc: readRawMessageHeader
|
|
52
|
+
});
|
|
53
|
+
this._packetAssembler.on("message", (messageChunk) => this._feed_messageChunk(messageChunk));
|
|
54
|
+
this._packetAssembler.on("newMessage", (info, data) => {
|
|
55
|
+
if (doPerfMonitoring) {
|
|
56
|
+
// record tick 0: when the first data is received
|
|
57
|
+
this._tick0 = (0, node_opcua_utils_1.get_clock_tick)();
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
*
|
|
61
|
+
* notify the observers that a new message is being built
|
|
62
|
+
* @event start_chunk
|
|
63
|
+
* @param info
|
|
64
|
+
* @param data
|
|
65
|
+
*/
|
|
66
|
+
this.emit("start_chunk", info, data);
|
|
67
|
+
});
|
|
68
|
+
this._securityDefeated = false;
|
|
69
|
+
this.totalBodySize = 0;
|
|
70
|
+
this.totalMessageSize = 0;
|
|
71
|
+
this.channelId = 0;
|
|
72
|
+
this.offsetBodyStart = 0;
|
|
73
|
+
this.sequenceHeader = null;
|
|
74
|
+
this._init_new();
|
|
75
|
+
}
|
|
76
|
+
dispose() {
|
|
77
|
+
this.removeAllListeners();
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Feed message builder with some data
|
|
81
|
+
* @method feed
|
|
82
|
+
* @param data
|
|
83
|
+
*/
|
|
84
|
+
feed(data) {
|
|
85
|
+
if (!this._securityDefeated && !this._hasReceivedError) {
|
|
86
|
+
this._packetAssembler.feed(data);
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
_decodeMessageBody(fullMessageBody) {
|
|
90
|
+
return true;
|
|
91
|
+
}
|
|
92
|
+
_read_headers(binaryStream) {
|
|
93
|
+
try {
|
|
94
|
+
this.messageHeader = (0, node_opcua_chunkmanager_1.readMessageHeader)(binaryStream);
|
|
95
|
+
(0, node_opcua_assert_1.assert)(binaryStream.length === 8, "expecting message header to be 8 bytes");
|
|
96
|
+
this.channelId = binaryStream.readUInt32();
|
|
97
|
+
(0, node_opcua_assert_1.assert)(binaryStream.length === 12);
|
|
98
|
+
// verifying secure ChannelId
|
|
99
|
+
if (this._expectedChannelId && this.channelId !== this._expectedChannelId) {
|
|
100
|
+
return this._report_error("Invalid secure channel Id");
|
|
101
|
+
}
|
|
102
|
+
return true;
|
|
103
|
+
}
|
|
104
|
+
catch (err) {
|
|
105
|
+
return false;
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
_report_error(errorMessage) {
|
|
109
|
+
this._hasReceivedError = true;
|
|
110
|
+
/**
|
|
111
|
+
* notify the observers that an error has occurred
|
|
112
|
+
* @event error
|
|
113
|
+
* @param error the error to raise
|
|
114
|
+
*/
|
|
115
|
+
debugLog("Error ", this.id, errorMessage);
|
|
116
|
+
// xx errorLog(new Error());
|
|
117
|
+
this.emit("error", new Error(errorMessage), this.sequenceHeader ? this.sequenceHeader.requestId : null);
|
|
118
|
+
return false;
|
|
119
|
+
}
|
|
120
|
+
_init_new() {
|
|
121
|
+
this._securityDefeated = false;
|
|
122
|
+
this._hasReceivedError = false;
|
|
123
|
+
this.totalBodySize = 0;
|
|
124
|
+
this.totalMessageSize = 0;
|
|
125
|
+
this.blocks = [];
|
|
126
|
+
this.messageChunks = [];
|
|
127
|
+
}
|
|
128
|
+
/**
|
|
129
|
+
* append a message chunk
|
|
130
|
+
* @method _append
|
|
131
|
+
* @param chunk
|
|
132
|
+
* @private
|
|
133
|
+
*/
|
|
134
|
+
_append(chunk) {
|
|
135
|
+
if (this._hasReceivedError) {
|
|
136
|
+
// the message builder is in error mode and further message chunks should be discarded.
|
|
137
|
+
return false;
|
|
138
|
+
}
|
|
139
|
+
this.messageChunks.push(chunk);
|
|
140
|
+
this.totalMessageSize += chunk.length;
|
|
141
|
+
const binaryStream = new node_opcua_binary_stream_1.BinaryStream(chunk);
|
|
142
|
+
if (!this._read_headers(binaryStream)) {
|
|
143
|
+
return this._report_error(`Invalid message header detected`);
|
|
144
|
+
}
|
|
145
|
+
(0, node_opcua_assert_1.assert)(binaryStream.length >= 12);
|
|
146
|
+
// verify message chunk length
|
|
147
|
+
if (this.messageHeader.length !== chunk.length) {
|
|
148
|
+
// tslint:disable:max-line-length
|
|
149
|
+
return this._report_error(`Invalid messageChunk size: the provided chunk is ${chunk.length} bytes long but header specifies ${this.messageHeader.length}`);
|
|
150
|
+
}
|
|
151
|
+
// the start of the message body block
|
|
152
|
+
const offsetBodyStart = binaryStream.length;
|
|
153
|
+
// the end of the message body block
|
|
154
|
+
const offsetBodyEnd = binaryStream.buffer.length;
|
|
155
|
+
this.totalBodySize += offsetBodyEnd - offsetBodyStart;
|
|
156
|
+
this.offsetBodyStart = offsetBodyStart;
|
|
157
|
+
// add message body to a queue
|
|
158
|
+
// note : Buffer.slice create a shared memory !
|
|
159
|
+
// use Buffer.clone
|
|
160
|
+
const sharedBuffer = chunk.slice(this.offsetBodyStart, offsetBodyEnd);
|
|
161
|
+
const clonedBuffer = (0, node_opcua_buffer_utils_1.createFastUninitializedBuffer)(sharedBuffer.length);
|
|
162
|
+
sharedBuffer.copy(clonedBuffer, 0, 0);
|
|
163
|
+
this.blocks.push(clonedBuffer);
|
|
164
|
+
return true;
|
|
165
|
+
}
|
|
166
|
+
_feed_messageChunk(chunk) {
|
|
167
|
+
(0, node_opcua_assert_1.assert)(chunk);
|
|
168
|
+
const messageHeader = (0, node_opcua_chunkmanager_1.readMessageHeader)(new node_opcua_binary_stream_1.BinaryStream(chunk));
|
|
169
|
+
/**
|
|
170
|
+
* notify the observers that new message chunk has been received
|
|
171
|
+
* @event chunk
|
|
172
|
+
* @param messageChunk the raw message chunk
|
|
173
|
+
*/
|
|
174
|
+
this.emit("chunk", chunk);
|
|
175
|
+
if (messageHeader.isFinal === "F") {
|
|
176
|
+
// last message
|
|
177
|
+
this._append(chunk);
|
|
178
|
+
if (this._hasReceivedError) {
|
|
179
|
+
return false;
|
|
180
|
+
}
|
|
181
|
+
const fullMessageBody = this.blocks.length === 1 ? this.blocks[0] : Buffer.concat(this.blocks);
|
|
182
|
+
if (doPerfMonitoring) {
|
|
183
|
+
// record tick 1: when a complete message has been received ( all chunks assembled)
|
|
184
|
+
this._tick1 = (0, node_opcua_utils_1.get_clock_tick)();
|
|
185
|
+
}
|
|
186
|
+
/**
|
|
187
|
+
* notify the observers that a full message has been received
|
|
188
|
+
* @event full_message_body
|
|
189
|
+
* @param full_message_body the full message body made of all concatenated chunks.
|
|
190
|
+
*/
|
|
191
|
+
this.emit("full_message_body", fullMessageBody);
|
|
192
|
+
this._decodeMessageBody(fullMessageBody);
|
|
193
|
+
// be ready for next block
|
|
194
|
+
this._init_new();
|
|
195
|
+
return true;
|
|
196
|
+
}
|
|
197
|
+
else if (messageHeader.isFinal === "A") {
|
|
198
|
+
return this._report_error("received and Abort Message");
|
|
199
|
+
}
|
|
200
|
+
else if (messageHeader.isFinal === "C") {
|
|
201
|
+
return this._append(chunk);
|
|
202
|
+
}
|
|
203
|
+
return false;
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
exports.MessageBuilderBase = MessageBuilderBase;
|
|
207
207
|
//# sourceMappingURL=message_builder_base.js.map
|