node-opcua-client 2.72.1 → 2.73.1
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/client_base.d.ts +23 -40
- package/dist/client_base.js +1 -0
- package/dist/client_base.js.map +1 -1
- package/dist/client_session.d.ts +2 -2
- package/dist/client_session.js.map +1 -1
- package/dist/private/client_base_impl.d.ts +5 -17
- package/dist/private/client_base_impl.js +144 -131
- package/dist/private/client_base_impl.js.map +1 -1
- package/dist/private/client_session_impl.js.map +1 -1
- package/dist/private/opcua_client_impl.js +10 -7
- package/dist/private/opcua_client_impl.js.map +1 -1
- package/dist/reconnection.js +57 -11
- package/dist/reconnection.js.map +1 -1
- package/dist/tools/findservers.js +2 -2
- package/dist/tools/findservers.js.map +1 -1
- package/package.json +34 -34
- package/source/client_base.ts +23 -40
- package/source/client_session.ts +4 -2
- package/source/private/client_base_impl.ts +181 -150
- package/source/private/client_session_impl.ts +1 -3
- package/source/private/opcua_client_impl.ts +14 -10
- package/source/reconnection.ts +65 -12
- package/source/tools/findservers.ts +2 -2
|
@@ -195,7 +195,9 @@ class ClockAdjustment {
|
|
|
195
195
|
*
|
|
196
196
|
* "connecting" ---[lost of connection]-----------> "reconnecting" ->[reconnection]
|
|
197
197
|
*
|
|
198
|
-
* "reconnecting" ---[reconnection successful]------> "
|
|
198
|
+
* "reconnecting" ---[reconnection successful]------> "reconnecting_newchannel_connected"
|
|
199
|
+
*
|
|
200
|
+
* "reconnecting_newchannel_connected" --(session failure) -->"reconnecting"
|
|
199
201
|
*
|
|
200
202
|
* "reconnecting" ---[reconnection failure]---------> [reconnection] ---> "reconnecting"
|
|
201
203
|
*
|
|
@@ -216,6 +218,7 @@ class ClientBaseImpl extends node_opcua_common_1.OPCUASecureObject {
|
|
|
216
218
|
options.certificateFile =
|
|
217
219
|
options.certificateFile || path.join(options.clientCertificateManager.rootDir, "own/certs/client_certificate.pem");
|
|
218
220
|
super(options);
|
|
221
|
+
this._inside_repairConnection = false;
|
|
219
222
|
this._instanceNumber = g_ClientCounter++;
|
|
220
223
|
this._internalState = "uninitialized";
|
|
221
224
|
this.applicationName = options.applicationName || "NodeOPCUA-Client";
|
|
@@ -226,7 +229,7 @@ class ClientBaseImpl extends node_opcua_common_1.OPCUASecureObject {
|
|
|
226
229
|
this.disconnecting = false;
|
|
227
230
|
this.clientCertificateManager = options.clientCertificateManager;
|
|
228
231
|
this._secureChannel = null;
|
|
229
|
-
this.
|
|
232
|
+
this._reconnectionIsCanceled = false;
|
|
230
233
|
this.endpointUrl = "";
|
|
231
234
|
this.clientName = options.clientName || "ClientSession";
|
|
232
235
|
// must be ZERO with Spec 1.0.2
|
|
@@ -253,59 +256,46 @@ class ClientBaseImpl extends node_opcua_common_1.OPCUASecureObject {
|
|
|
253
256
|
this.keepPendingSessionsOnDisconnect = options.keepPendingSessionsOnDisconnect || false;
|
|
254
257
|
this.discoveryUrl = options.discoveryUrl || "";
|
|
255
258
|
this._setInternalState("disconnected");
|
|
259
|
+
this._transportSettings = options.transportSettings || {};
|
|
256
260
|
}
|
|
257
261
|
/**
|
|
258
262
|
* total number of requests that been canceled due to timeout
|
|
259
|
-
* @property timedOutRequestCount
|
|
260
|
-
* @type {Number}
|
|
261
263
|
*/
|
|
262
264
|
get timedOutRequestCount() {
|
|
263
265
|
return this._timedOutRequestCount + (this._secureChannel ? this._secureChannel.timedOutRequestCount : 0);
|
|
264
266
|
}
|
|
265
267
|
/**
|
|
266
268
|
* total number of transactions performed by the client
|
|
267
|
-
|
|
268
|
-
* @type {Number}
|
|
269
|
-
*/
|
|
269
|
+
x */
|
|
270
270
|
get transactionsPerformed() {
|
|
271
271
|
return this._transactionsPerformed + (this._secureChannel ? this._secureChannel.transactionsPerformed : 0);
|
|
272
272
|
}
|
|
273
273
|
/**
|
|
274
274
|
* is true when the client has already requested the server end points.
|
|
275
|
-
* @property knowsServerEndpoint
|
|
276
|
-
* @type boolean
|
|
277
275
|
*/
|
|
278
276
|
get knowsServerEndpoint() {
|
|
279
277
|
return this._serverEndpoints && this._serverEndpoints.length > 0;
|
|
280
278
|
}
|
|
281
279
|
/**
|
|
282
280
|
* true if the client is trying to reconnect to the server after a connection break.
|
|
283
|
-
* @property isReconnecting
|
|
284
|
-
* @type {Boolean}
|
|
285
281
|
*/
|
|
286
282
|
get isReconnecting() {
|
|
287
283
|
return !!(this._secureChannel && this._secureChannel.isConnecting) || this._internalState !== "connected";
|
|
288
284
|
}
|
|
289
285
|
/**
|
|
290
286
|
* true if the connection strategy is set to automatically try to reconnect in case of failure
|
|
291
|
-
* @property reconnectOnFailure
|
|
292
|
-
* @type {Boolean}
|
|
293
287
|
*/
|
|
294
288
|
get reconnectOnFailure() {
|
|
295
289
|
return this.connectionStrategy.maxRetry > 0 || this.connectionStrategy.maxRetry === -1;
|
|
296
290
|
}
|
|
297
291
|
/**
|
|
298
292
|
* total number of bytes read by the client
|
|
299
|
-
* @property bytesRead
|
|
300
|
-
* @type {Number}
|
|
301
293
|
*/
|
|
302
294
|
get bytesRead() {
|
|
303
295
|
return this._byteRead + (this._secureChannel ? this._secureChannel.bytesRead : 0);
|
|
304
296
|
}
|
|
305
297
|
/**
|
|
306
298
|
* total number of bytes written by the client
|
|
307
|
-
* @property bytesWritten
|
|
308
|
-
* @type {Number}
|
|
309
299
|
*/
|
|
310
300
|
get bytesWritten() {
|
|
311
301
|
return this._byteWritten + (this._secureChannel ? this._secureChannel.bytesWritten : 0);
|
|
@@ -326,8 +316,11 @@ class ClientBaseImpl extends node_opcua_common_1.OPCUASecureObject {
|
|
|
326
316
|
_cancel_reconnection(callback) {
|
|
327
317
|
// _cancel_reconnection is invoked during disconnection
|
|
328
318
|
// when we detect that a reconnection is in progress..
|
|
329
|
-
|
|
330
|
-
|
|
319
|
+
if (!this.isReconnecting) {
|
|
320
|
+
warningLog("internal error : _cancel_reconnection should be used when reconnecting is in progress");
|
|
321
|
+
}
|
|
322
|
+
debugLog("canceling reconnection");
|
|
323
|
+
this._reconnectionIsCanceled = true;
|
|
331
324
|
// istanbul ignore next
|
|
332
325
|
if (!this._secureChannel) {
|
|
333
326
|
debugLog("_cancel_reconnection: Nothing to do !");
|
|
@@ -342,52 +335,66 @@ class ClientBaseImpl extends node_opcua_common_1.OPCUASecureObject {
|
|
|
342
335
|
});
|
|
343
336
|
}
|
|
344
337
|
_recreate_secure_channel(callback) {
|
|
345
|
-
debugLog("_recreate_secure_channel...", this._internalState);
|
|
338
|
+
debugLog("_recreate_secure_channel... while internalState is", this._internalState);
|
|
346
339
|
if (!this.knowsServerEndpoint) {
|
|
347
340
|
debugLog("Cannot reconnect , server endpoint is unknown");
|
|
348
341
|
return callback(new Error("Cannot reconnect, server endpoint is unknown"));
|
|
349
342
|
}
|
|
350
343
|
(0, node_opcua_assert_1.assert)(this.knowsServerEndpoint);
|
|
351
|
-
// xx ??? assert(!this.isReconnecting);
|
|
352
|
-
/**
|
|
353
|
-
* notifies the observer that the OPCUA is now trying to reestablish the connection
|
|
354
|
-
* after having received a connection break...
|
|
355
|
-
* @event start_reconnection
|
|
356
|
-
*
|
|
357
|
-
*/
|
|
358
344
|
this._setInternalState("reconnecting");
|
|
359
345
|
this.emit("start_reconnection"); // send after callback
|
|
360
|
-
this._destroy_secure_channel();
|
|
361
|
-
(0, node_opcua_assert_1.assert)(!this._secureChannel);
|
|
362
346
|
const infiniteConnectionRetry = {
|
|
363
347
|
initialDelay: this.connectionStrategy.initialDelay,
|
|
364
348
|
maxDelay: this.connectionStrategy.maxDelay,
|
|
365
349
|
maxRetry: -1
|
|
366
350
|
};
|
|
367
|
-
const
|
|
351
|
+
const _when_internal_error = (err, callback) => {
|
|
352
|
+
errorLog("INTERNAL ERROR", err.message);
|
|
353
|
+
callback(err);
|
|
354
|
+
};
|
|
355
|
+
const _when_reconnectionIsCanceled = (callback) => {
|
|
356
|
+
warningLog("attempt to recreate a new secure channel : suspended becasue reconnection is canceled !");
|
|
357
|
+
this.emit("reconnection_canceled");
|
|
358
|
+
return callback(new Error("Reconnection has been canceled - " + this.clientName));
|
|
359
|
+
};
|
|
360
|
+
const _failAndRetry = (err, message, callback) => {
|
|
368
361
|
debugLog("failAndRetry; ", message);
|
|
369
|
-
if (this.
|
|
370
|
-
|
|
371
|
-
return callback(new Error("Reconnection has been canceled - " + this.clientName));
|
|
362
|
+
if (this._reconnectionIsCanceled) {
|
|
363
|
+
return _when_reconnectionIsCanceled(callback);
|
|
372
364
|
}
|
|
365
|
+
this._destroy_secure_channel();
|
|
373
366
|
warningLog("client = ", this.clientName, message, err.message);
|
|
374
367
|
// else
|
|
375
368
|
// let retry a little bit later
|
|
376
369
|
this.emit("reconnection_attempt_has_failed", err, message); // send after callback
|
|
377
|
-
|
|
370
|
+
setImmediate(_attempt_to_recreate_secure_channel, callback);
|
|
378
371
|
};
|
|
379
|
-
const
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
372
|
+
const _when_connected = (callback) => {
|
|
373
|
+
this.emit("after_reconnection", null); // send after callback
|
|
374
|
+
(0, node_opcua_assert_1.assert)(this._secureChannel, "expecting a secureChannel here ");
|
|
375
|
+
// a new channel has be created and a new connection is established
|
|
376
|
+
debugLog(chalk.bgWhite.red("ClientBaseImpl: RECONNECTED !!!"));
|
|
377
|
+
this._setInternalState("reconnecting_newchannel_connected");
|
|
378
|
+
return callback();
|
|
379
|
+
};
|
|
380
|
+
const _attempt_to_recreate_secure_channel = (callback) => {
|
|
381
|
+
debugLog("attempt to recreate a new secure channel");
|
|
382
|
+
if (this._reconnectionIsCanceled) {
|
|
383
|
+
return _when_reconnectionIsCanceled(callback);
|
|
383
384
|
}
|
|
385
|
+
(0, node_opcua_assert_1.assert)(!this._secureChannel, "_attempt_to_recreate_secure_channel, expecting this._secureChannel not to exist");
|
|
384
386
|
this._internal_create_secure_channel(infiniteConnectionRetry, (err) => {
|
|
385
387
|
if (err) {
|
|
388
|
+
// istanbul ignore next
|
|
389
|
+
if (this._secureChannel) {
|
|
390
|
+
const err = new Error("_internal_create_secure_channel failed, expecting this._secureChannel not to exist");
|
|
391
|
+
return _when_internal_error(err, callback);
|
|
392
|
+
}
|
|
386
393
|
if (err.message.match(/ECONNREFUSED|ECONNABORTED/)) {
|
|
387
|
-
return
|
|
394
|
+
return _failAndRetry(err, "create secure channel failed with ECONNREFUSED|ECONNABORTED", callback);
|
|
388
395
|
}
|
|
389
396
|
if (err.message.match("Backoff aborted.")) {
|
|
390
|
-
return
|
|
397
|
+
return _failAndRetry(err, "cannot create secure channel (backoff aborted)", callback);
|
|
391
398
|
}
|
|
392
399
|
if (err.message.match("BadCertificateInvalid") ||
|
|
393
400
|
err.message.match(/_socket has been disconnected by third party/)) {
|
|
@@ -396,51 +403,36 @@ class ClientBaseImpl extends node_opcua_common_1.OPCUASecureObject {
|
|
|
396
403
|
// the server may have shut down the channel because its certificate
|
|
397
404
|
// has changed ....
|
|
398
405
|
// let request the server certificate again ....
|
|
399
|
-
debugLog(chalk.bgWhite.red("ClientBaseImpl: Server Certificate has changed." + " we need to retrieve server certificate again"));
|
|
400
406
|
return this.fetchServerCertificate(this.endpointUrl, (err1) => {
|
|
401
407
|
if (err1) {
|
|
402
|
-
|
|
403
|
-
return failAndRetry(err1, "trying to fetch new server certificate");
|
|
408
|
+
return _failAndRetry(err1, "Failing to fetch new server certificate", callback);
|
|
404
409
|
}
|
|
405
410
|
warningLog("new server certificate ", (0, node_opcua_crypto_1.makeSHA1Thumbprint)(this.serverCertificate).toString("hex"));
|
|
406
411
|
this._internal_create_secure_channel(infiniteConnectionRetry, (err3) => {
|
|
407
412
|
if (err3) {
|
|
408
|
-
return
|
|
413
|
+
return _failAndRetry(err3, "trying to create new channel with new certificate", callback);
|
|
409
414
|
}
|
|
410
|
-
|
|
411
|
-
this.emit("connected");
|
|
412
|
-
callback();
|
|
415
|
+
return _when_connected(callback);
|
|
413
416
|
});
|
|
414
417
|
});
|
|
415
418
|
}
|
|
416
|
-
|
|
417
|
-
|
|
419
|
+
else {
|
|
420
|
+
return _failAndRetry(err, "cannot create secure channel", callback);
|
|
421
|
+
}
|
|
418
422
|
}
|
|
419
423
|
else {
|
|
420
|
-
|
|
421
|
-
* notify the observers that the reconnection process has been completed
|
|
422
|
-
* @event after_reconnection
|
|
423
|
-
* @param err
|
|
424
|
-
*/
|
|
425
|
-
this.emit("after_reconnection", err); // send after callback
|
|
426
|
-
(0, node_opcua_assert_1.assert)(this._secureChannel, "expecting a secureChannel here ");
|
|
427
|
-
// a new channel has be created and a new connection is established
|
|
428
|
-
debugLog(chalk.bgWhite.red("ClientBaseImpl: RECONNECTED !!!"));
|
|
429
|
-
this._setInternalState("connected");
|
|
430
|
-
return callback();
|
|
424
|
+
return _when_connected(callback);
|
|
431
425
|
}
|
|
432
426
|
});
|
|
433
427
|
};
|
|
434
428
|
// create a secure channel
|
|
435
429
|
// a new secure channel must be established
|
|
436
|
-
|
|
437
|
-
_attempt_to_recreate_secure_channel();
|
|
438
|
-
});
|
|
430
|
+
_attempt_to_recreate_secure_channel(callback);
|
|
439
431
|
}
|
|
440
432
|
_internal_create_secure_channel(connectionStrategy, callback) {
|
|
441
433
|
(0, node_opcua_assert_1.assert)(this._secureChannel === null);
|
|
442
434
|
(0, node_opcua_assert_1.assert)(typeof this.endpointUrl === "string");
|
|
443
|
-
debugLog("_internal_create_secure_channel creating new ClientSecureChannelLayer");
|
|
435
|
+
debugLog("_internal_create_secure_channel creating new ClientSecureChannelLayer _internalState =", this._internalState);
|
|
444
436
|
const secureChannel = new node_opcua_secure_channel_1.ClientSecureChannelLayer({
|
|
445
437
|
connectionStrategy,
|
|
446
438
|
defaultSecureTokenLifetime: this.defaultSecureTokenLifetime,
|
|
@@ -448,36 +440,33 @@ class ClientBaseImpl extends node_opcua_common_1.OPCUASecureObject {
|
|
|
448
440
|
securityMode: this.securityMode,
|
|
449
441
|
securityPolicy: this.securityPolicy,
|
|
450
442
|
serverCertificate: this.serverCertificate,
|
|
451
|
-
tokenRenewalInterval: this.tokenRenewalInterval
|
|
443
|
+
tokenRenewalInterval: this.tokenRenewalInterval,
|
|
444
|
+
transportSettings: this._transportSettings
|
|
452
445
|
// transportTimeout:
|
|
453
446
|
});
|
|
447
|
+
secureChannel.on("backoff", (count, delay) => {
|
|
448
|
+
this.emit("backoff", count, delay);
|
|
449
|
+
});
|
|
450
|
+
secureChannel.on("abort", () => {
|
|
451
|
+
this.emit("abort");
|
|
452
|
+
});
|
|
454
453
|
secureChannel.protocolVersion = this.protocolVersion;
|
|
455
454
|
this._secureChannel = secureChannel;
|
|
456
455
|
async.series([
|
|
457
456
|
// ------------------------------------------------- STEP 2 : OpenSecureChannel
|
|
458
|
-
(
|
|
457
|
+
(innerCallback) => {
|
|
459
458
|
debugLog("_internal_create_secure_channel before secureChannel.create");
|
|
460
459
|
secureChannel.create(this.endpointUrl, (err) => {
|
|
461
460
|
debugLog("_internal_create_secure_channel after secureChannel.create");
|
|
462
461
|
if (!this._secureChannel) {
|
|
463
462
|
debugLog("_secureChannel has been closed during the transaction !");
|
|
464
|
-
|
|
463
|
+
(0, node_opcua_assert_1.assert)(this.disconnecting);
|
|
464
|
+
return innerCallback(new Error("Secure Channel Closed"));
|
|
465
465
|
}
|
|
466
|
-
if (err) {
|
|
467
|
-
debugLog(chalk.yellow("Cannot create secureChannel"), err.message ? chalk.cyan(err.message) : "");
|
|
468
|
-
this._destroy_secure_channel();
|
|
469
|
-
}
|
|
470
|
-
else {
|
|
471
|
-
(0, node_opcua_assert_1.assert)(this._secureChannel !== null);
|
|
466
|
+
if (!err) {
|
|
472
467
|
this._install_secure_channel_event_handlers(secureChannel);
|
|
473
468
|
}
|
|
474
|
-
|
|
475
|
-
});
|
|
476
|
-
secureChannel.on("backoff", (count, delay) => {
|
|
477
|
-
this.emit("backoff", count, delay);
|
|
478
|
-
});
|
|
479
|
-
secureChannel.on("abort", () => {
|
|
480
|
-
this.emit("abort");
|
|
469
|
+
innerCallback(err);
|
|
481
470
|
});
|
|
482
471
|
},
|
|
483
472
|
// ------------------------------------------------- STEP 3 : GetEndpointsRequest
|
|
@@ -485,9 +474,10 @@ class ClientBaseImpl extends node_opcua_common_1.OPCUASecureObject {
|
|
|
485
474
|
(0, node_opcua_assert_1.assert)(this._secureChannel !== null);
|
|
486
475
|
if (!this.knowsServerEndpoint) {
|
|
487
476
|
this.getEndpoints((err /*, endpoints?: EndpointDescription[]*/) => {
|
|
488
|
-
if (this._secureChannel
|
|
477
|
+
if (!this._secureChannel) {
|
|
478
|
+
debugLog("_secureChannel has been closed during the transaction ! (while getEndpoints)");
|
|
489
479
|
(0, node_opcua_assert_1.assert)(this.disconnecting);
|
|
490
|
-
innerCallback(new Error("
|
|
480
|
+
return innerCallback(new Error("Secure Channel Closed"));
|
|
491
481
|
}
|
|
492
482
|
innerCallback(err ? err : undefined);
|
|
493
483
|
});
|
|
@@ -500,8 +490,15 @@ class ClientBaseImpl extends node_opcua_common_1.OPCUASecureObject {
|
|
|
500
490
|
], (err) => {
|
|
501
491
|
if (err) {
|
|
502
492
|
debugLog("Inner create secure channel has failed", err.message);
|
|
503
|
-
this._secureChannel
|
|
504
|
-
|
|
493
|
+
if (this._secureChannel) {
|
|
494
|
+
this._secureChannel.abortConnection(() => {
|
|
495
|
+
this._destroy_secure_channel();
|
|
496
|
+
callback(err);
|
|
497
|
+
});
|
|
498
|
+
}
|
|
499
|
+
else {
|
|
500
|
+
callback(err);
|
|
501
|
+
}
|
|
505
502
|
}
|
|
506
503
|
else {
|
|
507
504
|
(0, node_opcua_assert_1.assert)(this._secureChannel !== null);
|
|
@@ -714,10 +711,16 @@ class ClientBaseImpl extends node_opcua_common_1.OPCUASecureObject {
|
|
|
714
711
|
if (!this._secureChannel) {
|
|
715
712
|
// this may happen if the Server has closed the connection abruptly for some unknown reason
|
|
716
713
|
// or if the tcp connection has been broken.
|
|
717
|
-
return callback(new Error("No SecureChannel , connection may have been canceled abruptly by server"));
|
|
714
|
+
return callback(new Error("performMessageTransaction: No SecureChannel , connection may have been canceled abruptly by server"));
|
|
718
715
|
}
|
|
719
|
-
if (this._internalState !== "connected" &&
|
|
720
|
-
|
|
716
|
+
if (this._internalState !== "connected" &&
|
|
717
|
+
this._internalState !== "reconnecting_newchannel_connected" &&
|
|
718
|
+
this._internalState !== "connecting" &&
|
|
719
|
+
this._internalState !== "reconnecting") {
|
|
720
|
+
return callback(new Error("performMessageTransaction: Invalid client state " +
|
|
721
|
+
this._internalState +
|
|
722
|
+
" while performing a transaction " +
|
|
723
|
+
request.constructor.name));
|
|
721
724
|
}
|
|
722
725
|
(0, node_opcua_assert_1.assert)(this._secureChannel);
|
|
723
726
|
(0, node_opcua_assert_1.assert)(request);
|
|
@@ -914,7 +917,8 @@ class ClientBaseImpl extends node_opcua_common_1.OPCUASecureObject {
|
|
|
914
917
|
}
|
|
915
918
|
return callback();
|
|
916
919
|
}
|
|
917
|
-
|
|
920
|
+
debugLog("disconnecting client! (will set reconnectionIsCanceled to true");
|
|
921
|
+
this._reconnectionIsCanceled = true;
|
|
918
922
|
this.disconnecting = true;
|
|
919
923
|
if (this._tmpClient) {
|
|
920
924
|
this._tmpClient.disconnect((err) => {
|
|
@@ -926,7 +930,7 @@ class ClientBaseImpl extends node_opcua_common_1.OPCUASecureObject {
|
|
|
926
930
|
return;
|
|
927
931
|
}
|
|
928
932
|
debugLog("ClientBaseImpl#disconnect", this.endpointUrl);
|
|
929
|
-
if (this.isReconnecting && !this.
|
|
933
|
+
if (this.isReconnecting && !this._reconnectionIsCanceled) {
|
|
930
934
|
debugLog("ClientBaseImpl#disconnect called while reconnection is in progress");
|
|
931
935
|
// let's abort the reconnection process
|
|
932
936
|
this._cancel_reconnection((err) => {
|
|
@@ -1112,9 +1116,10 @@ class ClientBaseImpl extends node_opcua_common_1.OPCUASecureObject {
|
|
|
1112
1116
|
debugLog(" DESTROYING SECURE CHANNEL (isTransactionInProgress ?", this._secureChannel.isTransactionInProgress(), ")");
|
|
1113
1117
|
}
|
|
1114
1118
|
this._accumulate_statistics();
|
|
1115
|
-
this._secureChannel
|
|
1116
|
-
this._secureChannel.removeAllListeners();
|
|
1119
|
+
const secureChannel = this._secureChannel;
|
|
1117
1120
|
this._secureChannel = null;
|
|
1121
|
+
secureChannel.dispose();
|
|
1122
|
+
secureChannel.removeAllListeners();
|
|
1118
1123
|
}
|
|
1119
1124
|
}
|
|
1120
1125
|
_close_pending_sessions(callback) {
|
|
@@ -1194,6 +1199,7 @@ class ClientBaseImpl extends node_opcua_common_1.OPCUASecureObject {
|
|
|
1194
1199
|
});
|
|
1195
1200
|
secureChannel.on("close", (err) => {
|
|
1196
1201
|
debugLog(chalk.yellow.bold(" ClientBaseImpl emitting close"), err === null || err === void 0 ? void 0 : err.message);
|
|
1202
|
+
this._destroy_secure_channel();
|
|
1197
1203
|
if (!err || !this.reconnectOnFailure) {
|
|
1198
1204
|
// this is a normal close operation initiated by us
|
|
1199
1205
|
/**
|
|
@@ -1201,14 +1207,17 @@ class ClientBaseImpl extends node_opcua_common_1.OPCUASecureObject {
|
|
|
1201
1207
|
* @param error
|
|
1202
1208
|
*/
|
|
1203
1209
|
this.emit("close", err);
|
|
1204
|
-
setImmediate(() => this._destroy_secure_channel());
|
|
1205
1210
|
}
|
|
1206
1211
|
else {
|
|
1207
1212
|
/**
|
|
1208
1213
|
* @event connection_lost
|
|
1209
1214
|
*/
|
|
1210
|
-
this.emit("
|
|
1211
|
-
this.
|
|
1215
|
+
// this.emit("close", err);
|
|
1216
|
+
if (this.reconnectOnFailure && this._internalState !== "reconnecting") {
|
|
1217
|
+
debugLog(" ClientBaseImpl emitting connection_lost");
|
|
1218
|
+
this.emit("connection_lost", err === null || err === void 0 ? void 0 : err.message); // instead of "close"
|
|
1219
|
+
this._repairConnection();
|
|
1220
|
+
}
|
|
1212
1221
|
}
|
|
1213
1222
|
});
|
|
1214
1223
|
secureChannel.on("timed_out_request", (request) => {
|
|
@@ -1221,44 +1230,48 @@ class ClientBaseImpl extends node_opcua_common_1.OPCUASecureObject {
|
|
|
1221
1230
|
});
|
|
1222
1231
|
}
|
|
1223
1232
|
_repairConnection() {
|
|
1224
|
-
|
|
1225
|
-
|
|
1226
|
-
|
|
1227
|
-
|
|
1228
|
-
|
|
1229
|
-
|
|
1230
|
-
|
|
1231
|
-
|
|
1232
|
-
|
|
1233
|
-
|
|
1234
|
-
|
|
1235
|
-
|
|
1236
|
-
|
|
1237
|
-
|
|
1238
|
-
|
|
1239
|
-
|
|
1240
|
-
|
|
1241
|
-
|
|
1242
|
-
|
|
1243
|
-
|
|
1244
|
-
|
|
1245
|
-
|
|
1246
|
-
warningLog("I will retry OPCUA client reconnection in 5 seconds");
|
|
1247
|
-
setTimeout(() => this._repairConnection(), 5000);
|
|
1248
|
-
});
|
|
1249
|
-
return;
|
|
1250
|
-
}
|
|
1251
|
-
else {
|
|
1252
|
-
/**
|
|
1253
|
-
* @event connection_reestablished
|
|
1254
|
-
* send when the connection is reestablished after a connection break
|
|
1255
|
-
*/
|
|
1256
|
-
this.emit("connection_reestablished");
|
|
1257
|
-
this._setInternalState("connected");
|
|
1233
|
+
if (this._inside_repairConnection) {
|
|
1234
|
+
errorLog("_repairConnection already in progress ", this._internalState);
|
|
1235
|
+
return;
|
|
1236
|
+
}
|
|
1237
|
+
this._inside_repairConnection = true;
|
|
1238
|
+
debugLog("recreating new secure channel ", this._internalState);
|
|
1239
|
+
this._recreate_secure_channel((err1) => {
|
|
1240
|
+
debugLog("secureChannel#on(close) => _recreate_secure_channel returns ", err1 ? err1.message : "OK");
|
|
1241
|
+
if (err1) {
|
|
1242
|
+
errorLog("_recreate_secure_channel has failed: err = ", err1.message);
|
|
1243
|
+
this.emit("close", err1);
|
|
1244
|
+
this._setInternalState("disconnected");
|
|
1245
|
+
this._inside_repairConnection = false;
|
|
1246
|
+
return;
|
|
1247
|
+
}
|
|
1248
|
+
else {
|
|
1249
|
+
this._finalReconnectionStep((err2) => {
|
|
1250
|
+
if (err2) {
|
|
1251
|
+
// istanbul ignore next
|
|
1252
|
+
if (doDebug) {
|
|
1253
|
+
debugLog("connection_reestablished has failed");
|
|
1254
|
+
debugLog("err= ", err2.message);
|
|
1258
1255
|
}
|
|
1259
|
-
|
|
1260
|
-
|
|
1261
|
-
|
|
1256
|
+
// we still need to retry connecting here !!!
|
|
1257
|
+
debugLog("Disconnected following reconnection failure", err2.message);
|
|
1258
|
+
debugLog(`I will retry OPCUA client reconnection in ${client_base_1.OPCUAClientBase.retryDelay / 1000} seconds`);
|
|
1259
|
+
this._inside_repairConnection = false;
|
|
1260
|
+
this._destroy_secure_channel();
|
|
1261
|
+
setTimeout(() => this._repairConnection(), client_base_1.OPCUAClientBase.retryDelay);
|
|
1262
|
+
return;
|
|
1263
|
+
}
|
|
1264
|
+
else {
|
|
1265
|
+
/**
|
|
1266
|
+
* @event connection_reestablished
|
|
1267
|
+
* send when the connection is reestablished after a connection break
|
|
1268
|
+
*/
|
|
1269
|
+
this.emit("connection_reestablished");
|
|
1270
|
+
this._setInternalState("connected");
|
|
1271
|
+
this._inside_repairConnection = false;
|
|
1272
|
+
}
|
|
1273
|
+
});
|
|
1274
|
+
}
|
|
1262
1275
|
});
|
|
1263
1276
|
}
|
|
1264
1277
|
_finalReconnectionStep(callback) {
|