node-opcua-transport 2.128.0 → 2.131.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/client_tcp_transport.js +1 -2
- package/dist/source/client_tcp_transport.js.map +1 -1
- package/dist/source/message_builder_base.d.ts +2 -16
- package/dist/source/message_builder_base.js +133 -122
- package/dist/source/message_builder_base.js.map +1 -1
- package/dist/source/tcp_transport.d.ts +6 -13
- package/dist/source/tcp_transport.js +95 -73
- package/dist/source/tcp_transport.js.map +1 -1
- package/dist/test_helpers/half_com_channel.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +5 -5
- package/source/client_tcp_transport.ts +1 -5
- package/source/message_builder_base.ts +44 -46
- package/source/tcp_transport.ts +62 -62
package/source/tcp_transport.ts
CHANGED
|
@@ -138,6 +138,11 @@ export interface TCP_transport {
|
|
|
138
138
|
// tslint:disable:class-name
|
|
139
139
|
export class TCP_transport extends EventEmitter {
|
|
140
140
|
private static registry = new ObjectRegistry();
|
|
141
|
+
/**
|
|
142
|
+
* the size of the header in bytes
|
|
143
|
+
* @default 8
|
|
144
|
+
*/
|
|
145
|
+
public static readonly headerSize = 8;
|
|
141
146
|
|
|
142
147
|
/**
|
|
143
148
|
* indicates the version number of the OPCUA protocol used
|
|
@@ -156,19 +161,14 @@ export class TCP_transport extends EventEmitter {
|
|
|
156
161
|
public name: string;
|
|
157
162
|
|
|
158
163
|
public _socket: ISocketLike | null;
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
private _theCallback?: (err?: Error | null, data?: Buffer) => void;
|
|
168
|
-
private _on_error_during_one_time_message_receiver: ((hadError: boolean) => void) | undefined;
|
|
169
|
-
private packetAssembler?: PacketAssembler;
|
|
170
|
-
private _timeout: number;
|
|
171
|
-
private _isDisconnecting = false;
|
|
164
|
+
#_closedEmitted: Error | string | undefined = undefined;
|
|
165
|
+
|
|
166
|
+
#_timerId: NodeJS.Timeout | null;
|
|
167
|
+
#_theCallback?: (err?: Error | null, data?: Buffer) => void;
|
|
168
|
+
#_on_error_during_one_time_message_receiver: ((hadError: boolean) => void) | undefined;
|
|
169
|
+
#packetAssembler?: PacketAssembler;
|
|
170
|
+
#_timeout: number;
|
|
171
|
+
#_isDisconnecting = false;
|
|
172
172
|
protected _theCloseError: Error | null = null;
|
|
173
173
|
|
|
174
174
|
constructor() {
|
|
@@ -177,10 +177,11 @@ export class TCP_transport extends EventEmitter {
|
|
|
177
177
|
this.name = this.constructor.name + counter;
|
|
178
178
|
counter += 1;
|
|
179
179
|
|
|
180
|
-
this._timerId = null;
|
|
181
|
-
this._timeout = 5000; // 5 seconds timeout
|
|
182
180
|
this._socket = null;
|
|
183
|
-
|
|
181
|
+
|
|
182
|
+
this.#_timerId = null;
|
|
183
|
+
this.#_timeout = 5000; // 5 seconds timeout
|
|
184
|
+
this.#_theCallback = undefined;
|
|
184
185
|
|
|
185
186
|
this.maxMessageSize = 0;
|
|
186
187
|
this.maxChunkCount = 0;
|
|
@@ -191,7 +192,6 @@ export class TCP_transport extends EventEmitter {
|
|
|
191
192
|
this.bytesWritten = 0;
|
|
192
193
|
this.bytesRead = 0;
|
|
193
194
|
|
|
194
|
-
this._theCallback = undefined;
|
|
195
195
|
this.chunkWrittenCount = 0;
|
|
196
196
|
this.chunkReadCount = 0;
|
|
197
197
|
|
|
@@ -210,7 +210,7 @@ export class TCP_transport extends EventEmitter {
|
|
|
210
210
|
str += " bytesWritten...... = " + this.bytesWritten + "\n";
|
|
211
211
|
str += " chunkWrittenCount. = " + this.chunkWrittenCount + "\n";
|
|
212
212
|
str += " chunkReadCount.... = " + this.chunkReadCount + "\n";
|
|
213
|
-
str += " closeEmitted ? ....= " + this
|
|
213
|
+
str += " closeEmitted ? ....= " + this.#_closedEmitted + "\n";
|
|
214
214
|
return str;
|
|
215
215
|
}
|
|
216
216
|
|
|
@@ -246,21 +246,21 @@ export class TCP_transport extends EventEmitter {
|
|
|
246
246
|
}
|
|
247
247
|
|
|
248
248
|
// reinstall packetAssembler with correct limits
|
|
249
|
-
this
|
|
249
|
+
this.#_install_packetAssembler();
|
|
250
250
|
}
|
|
251
251
|
|
|
252
252
|
public get timeout(): number {
|
|
253
|
-
return this
|
|
253
|
+
return this.#_timeout;
|
|
254
254
|
}
|
|
255
255
|
public set timeout(value: number) {
|
|
256
|
-
assert(!this
|
|
256
|
+
assert(!this.#_timerId);
|
|
257
257
|
debugLog("Setting socket " + this.name + " timeout = ", value);
|
|
258
|
-
this
|
|
258
|
+
this.#_timeout = value;
|
|
259
259
|
}
|
|
260
260
|
|
|
261
261
|
public dispose(): void {
|
|
262
262
|
this._cleanup_timers();
|
|
263
|
-
assert(!this
|
|
263
|
+
assert(!this.#_timerId);
|
|
264
264
|
if (this._socket) {
|
|
265
265
|
const gracefully = true;
|
|
266
266
|
if (gracefully) {
|
|
@@ -292,7 +292,7 @@ export class TCP_transport extends EventEmitter {
|
|
|
292
292
|
}
|
|
293
293
|
|
|
294
294
|
public isDisconnecting(): boolean {
|
|
295
|
-
return !this._socket || this
|
|
295
|
+
return !this._socket || this.#_isDisconnecting;
|
|
296
296
|
}
|
|
297
297
|
/**
|
|
298
298
|
* disconnect the TCP layer and close the underlying socket.
|
|
@@ -304,14 +304,14 @@ export class TCP_transport extends EventEmitter {
|
|
|
304
304
|
*/
|
|
305
305
|
public disconnect(callback: ErrorCallback): void {
|
|
306
306
|
assert(typeof callback === "function", "expecting a callback function, but got " + callback);
|
|
307
|
-
if (!this._socket || this
|
|
308
|
-
if (!this
|
|
307
|
+
if (!this._socket || this.#_isDisconnecting) {
|
|
308
|
+
if (!this.#_isDisconnecting) {
|
|
309
309
|
this.dispose();
|
|
310
310
|
}
|
|
311
311
|
callback();
|
|
312
312
|
return;
|
|
313
313
|
}
|
|
314
|
-
this
|
|
314
|
+
this.#_isDisconnecting = true;
|
|
315
315
|
|
|
316
316
|
this._cleanup_timers();
|
|
317
317
|
|
|
@@ -343,22 +343,22 @@ export class TCP_transport extends EventEmitter {
|
|
|
343
343
|
}
|
|
344
344
|
}
|
|
345
345
|
|
|
346
|
-
|
|
347
|
-
if (this
|
|
348
|
-
this
|
|
349
|
-
this
|
|
346
|
+
#_install_packetAssembler() {
|
|
347
|
+
if (this.#packetAssembler) {
|
|
348
|
+
this.#packetAssembler.removeAllListeners();
|
|
349
|
+
this.#packetAssembler = undefined;
|
|
350
350
|
}
|
|
351
351
|
|
|
352
352
|
// install packet assembler ...
|
|
353
|
-
this
|
|
353
|
+
this.#packetAssembler = new PacketAssembler({
|
|
354
354
|
readChunkFunc: readRawMessageHeader,
|
|
355
|
-
minimumSizeInBytes:
|
|
355
|
+
minimumSizeInBytes: TCP_transport.headerSize,
|
|
356
356
|
maxChunkSize: this.receiveBufferSize //Math.max(this.receiveBufferSize, this.sendBufferSize)
|
|
357
357
|
});
|
|
358
358
|
|
|
359
|
-
this
|
|
359
|
+
this.#packetAssembler.on("chunk", (chunk: Buffer) => this._on_message_chunk_received(chunk));
|
|
360
360
|
|
|
361
|
-
this
|
|
361
|
+
this.#packetAssembler.on("error", (err, code) => {
|
|
362
362
|
let statusCode = StatusCodes2.BadTcpMessageTooLarge;
|
|
363
363
|
switch (code) {
|
|
364
364
|
case PacketAssemblerErrorCode.ChunkSizeExceeded:
|
|
@@ -378,9 +378,9 @@ export class TCP_transport extends EventEmitter {
|
|
|
378
378
|
assert(socket);
|
|
379
379
|
assert(!this._socket, "already have a socket");
|
|
380
380
|
this._socket = socket;
|
|
381
|
-
this
|
|
381
|
+
this.#_closedEmitted = undefined;
|
|
382
382
|
this._theCloseError = null;
|
|
383
|
-
assert(this
|
|
383
|
+
assert(this.#_closedEmitted === undefined, "TCP Transport has already been closed !");
|
|
384
384
|
|
|
385
385
|
this._socket.setKeepAlive(true);
|
|
386
386
|
// Setting true for noDelay will immediately fire off data each time socket.write() is called.
|
|
@@ -393,7 +393,7 @@ export class TCP_transport extends EventEmitter {
|
|
|
393
393
|
// istanbul ignore next
|
|
394
394
|
doDebug && debugLog(" TCP_transport#_install_socket ", this.name);
|
|
395
395
|
|
|
396
|
-
this
|
|
396
|
+
this.#_install_packetAssembler();
|
|
397
397
|
|
|
398
398
|
this._socket
|
|
399
399
|
.on("data", (data: Buffer) => this._on_socket_data(data))
|
|
@@ -452,16 +452,16 @@ export class TCP_transport extends EventEmitter {
|
|
|
452
452
|
*
|
|
453
453
|
*/
|
|
454
454
|
protected _install_one_time_message_receiver(callback: CallbackWithData): void {
|
|
455
|
-
assert(!this
|
|
455
|
+
assert(!this.#_theCallback, "callback already set");
|
|
456
456
|
assert(typeof callback === "function");
|
|
457
457
|
this._start_one_time_message_receiver(callback);
|
|
458
458
|
}
|
|
459
459
|
|
|
460
460
|
private _fulfill_pending_promises(err: Error | null, data?: Buffer): boolean {
|
|
461
|
-
if (!this
|
|
461
|
+
if (!this.#_theCallback) return false;
|
|
462
462
|
doDebugFlow && errorLog("_fulfill_pending_promises from", new Error().stack);
|
|
463
|
-
const callback = this
|
|
464
|
-
this
|
|
463
|
+
const callback = this.#_theCallback;
|
|
464
|
+
this.#_theCallback = undefined;
|
|
465
465
|
callback(err, data);
|
|
466
466
|
return true;
|
|
467
467
|
}
|
|
@@ -479,20 +479,20 @@ export class TCP_transport extends EventEmitter {
|
|
|
479
479
|
}
|
|
480
480
|
|
|
481
481
|
private _cleanup_timers() {
|
|
482
|
-
if (this
|
|
483
|
-
clearTimeout(this
|
|
484
|
-
this
|
|
482
|
+
if (this.#_timerId) {
|
|
483
|
+
clearTimeout(this.#_timerId);
|
|
484
|
+
this.#_timerId = null;
|
|
485
485
|
}
|
|
486
486
|
}
|
|
487
487
|
|
|
488
488
|
private _start_one_time_message_receiver(callback: CallbackWithData) {
|
|
489
|
-
assert(!this
|
|
489
|
+
assert(!this.#_timerId && !this.#_on_error_during_one_time_message_receiver, "timer already started");
|
|
490
490
|
|
|
491
491
|
const _cleanUp = () => {
|
|
492
492
|
this._cleanup_timers();
|
|
493
|
-
if (this
|
|
494
|
-
this._socket?.removeListener("close", this
|
|
495
|
-
this
|
|
493
|
+
if (this.#_on_error_during_one_time_message_receiver) {
|
|
494
|
+
this._socket?.removeListener("close", this.#_on_error_during_one_time_message_receiver);
|
|
495
|
+
this.#_on_error_during_one_time_message_receiver = undefined;
|
|
496
496
|
}
|
|
497
497
|
};
|
|
498
498
|
|
|
@@ -504,40 +504,40 @@ export class TCP_transport extends EventEmitter {
|
|
|
504
504
|
this.dispose();
|
|
505
505
|
};
|
|
506
506
|
// Setup timeout detection timer ....
|
|
507
|
-
this
|
|
508
|
-
this
|
|
507
|
+
this.#_timerId = setTimeout(() => {
|
|
508
|
+
this.#_timerId = null;
|
|
509
509
|
onTimeout();
|
|
510
510
|
}, this.timeout);
|
|
511
511
|
|
|
512
512
|
// also monitored
|
|
513
513
|
if (this._socket) {
|
|
514
514
|
// to do = intercept socket error as well
|
|
515
|
-
this
|
|
515
|
+
this.#_on_error_during_one_time_message_receiver = (hadError: boolean) => {
|
|
516
516
|
const err = new Error(
|
|
517
517
|
`ERROR in waiting for data on socket ( timeout was = ${this.timeout} ms) hadError` + hadError
|
|
518
518
|
);
|
|
519
519
|
this._emitClose(err);
|
|
520
520
|
this._fulfill_pending_promises(err);
|
|
521
521
|
};
|
|
522
|
-
this._socket.prependOnceListener("close", this
|
|
522
|
+
this._socket.prependOnceListener("close", this.#_on_error_during_one_time_message_receiver);
|
|
523
523
|
}
|
|
524
524
|
|
|
525
525
|
const _callback = callback;
|
|
526
|
-
this
|
|
526
|
+
this.#_theCallback = (err?: Error | null, data?: Buffer) => {
|
|
527
527
|
_cleanUp();
|
|
528
|
-
this
|
|
528
|
+
this.#_theCallback = undefined;
|
|
529
529
|
_callback(err!, data);
|
|
530
530
|
};
|
|
531
531
|
}
|
|
532
532
|
|
|
533
533
|
private _on_socket_data(data: Buffer): void {
|
|
534
534
|
// istanbul ignore next
|
|
535
|
-
if (!this
|
|
535
|
+
if (!this.#packetAssembler) {
|
|
536
536
|
throw new Error("internal Error");
|
|
537
537
|
}
|
|
538
538
|
this.bytesRead += data.length;
|
|
539
539
|
if (data.length > 0) {
|
|
540
|
-
this
|
|
540
|
+
this.#packetAssembler.feed(data);
|
|
541
541
|
}
|
|
542
542
|
}
|
|
543
543
|
|
|
@@ -547,7 +547,7 @@ export class TCP_transport extends EventEmitter {
|
|
|
547
547
|
debugLog(chalk.red(` SOCKET CLOSE ${this.name}: `), chalk.yellow("had_error ="), chalk.cyan(hadError.toString()));
|
|
548
548
|
}
|
|
549
549
|
this.dispose();
|
|
550
|
-
if (this
|
|
550
|
+
if (this.#_theCallback) return;
|
|
551
551
|
// if (hadError) {
|
|
552
552
|
// if (this._socket) {
|
|
553
553
|
// this._socket.destroy();
|
|
@@ -560,8 +560,8 @@ export class TCP_transport extends EventEmitter {
|
|
|
560
560
|
err = err || this._theCloseError;
|
|
561
561
|
doDebugFlow && warningLog("_emitClose ", err?.message || "", "from", new Error().stack);
|
|
562
562
|
|
|
563
|
-
if (!this
|
|
564
|
-
this
|
|
563
|
+
if (!this.#_closedEmitted) {
|
|
564
|
+
this.#_closedEmitted = err || "noError";
|
|
565
565
|
this.emit("close", err || null);
|
|
566
566
|
// if (this._theCallback) {
|
|
567
567
|
// const callback = this._theCallback;
|
|
@@ -569,10 +569,10 @@ export class TCP_transport extends EventEmitter {
|
|
|
569
569
|
// callback(err || null);
|
|
570
570
|
// }
|
|
571
571
|
} else {
|
|
572
|
-
debugLog("Already emitted close event", (this
|
|
572
|
+
debugLog("Already emitted close event", (this.#_closedEmitted as any).message);
|
|
573
573
|
debugLog("err = ", err?.message);
|
|
574
574
|
debugLog("");
|
|
575
|
-
debugLog("Already emitted close event", this
|
|
575
|
+
debugLog("Already emitted close event", this.#_closedEmitted);
|
|
576
576
|
debugLog("err = ", err?.message, err);
|
|
577
577
|
}
|
|
578
578
|
}
|