node-opcua-client 2.166.0 → 2.168.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/alarms_and_conditions/client_alarm_tools.d.ts +1 -1
- package/dist/alarms_and_conditions/client_alarm_tools.js +2 -2
- package/dist/alarms_and_conditions/client_alarm_tools.js.map +1 -1
- package/dist/alarms_and_conditions/client_tools.d.ts +3 -0
- package/dist/alarms_and_conditions/client_tools.js +2 -2
- package/dist/alarms_and_conditions/client_tools.js.map +1 -1
- package/dist/client_base.d.ts +47 -40
- package/dist/client_base.js +5 -6
- package/dist/client_base.js.map +1 -1
- package/dist/client_monitored_item.d.ts +7 -7
- package/dist/client_monitored_item.js.map +1 -1
- package/dist/client_monitored_item_base.d.ts +12 -13
- package/dist/client_monitored_item_group.d.ts +5 -5
- package/dist/client_monitored_item_toolbox.d.ts +6 -7
- package/dist/client_monitored_item_toolbox.js.map +1 -1
- package/dist/client_session.d.ts +19 -23
- package/dist/client_session.js.map +1 -1
- package/dist/client_session_keepalive_manager.d.ts +1 -1
- package/dist/client_session_keepalive_manager.js +6 -6
- package/dist/client_session_keepalive_manager.js.map +1 -1
- package/dist/client_subscription.d.ts +11 -12
- package/dist/client_subscription.js.map +1 -1
- package/dist/client_utils.d.ts +3 -3
- package/dist/client_utils.js.map +1 -1
- package/dist/common.d.ts +12 -12
- package/dist/index.d.ts +26 -27
- package/dist/index.js +65 -66
- package/dist/index.js.map +1 -1
- package/dist/opcua_client.d.ts +17 -19
- package/dist/opcua_client.js.map +1 -1
- package/dist/private/client_base_impl.d.ts +19 -18
- package/dist/private/client_base_impl.js +220 -192
- package/dist/private/client_base_impl.js.map +1 -1
- package/dist/private/client_monitored_item_group_impl.d.ts +4 -5
- package/dist/private/client_monitored_item_group_impl.js +1 -1
- package/dist/private/client_monitored_item_group_impl.js.map +1 -1
- package/dist/private/client_monitored_item_impl.d.ts +9 -10
- package/dist/private/client_monitored_item_impl.js.map +1 -1
- package/dist/private/client_publish_engine.d.ts +3 -3
- package/dist/private/client_publish_engine.js +6 -7
- package/dist/private/client_publish_engine.js.map +1 -1
- package/dist/private/client_session_impl.d.ts +24 -25
- package/dist/private/client_session_impl.js +14 -10
- package/dist/private/client_session_impl.js.map +1 -1
- package/dist/private/client_subscription_impl.d.ts +10 -11
- package/dist/private/client_subscription_impl.js +12 -11
- package/dist/private/client_subscription_impl.js.map +1 -1
- package/dist/private/i_private_client.d.ts +7 -7
- package/dist/private/opcua_client_impl.d.ts +12 -9
- package/dist/private/opcua_client_impl.js +58 -48
- package/dist/private/opcua_client_impl.js.map +1 -1
- package/dist/private/performance.js.map +1 -1
- package/dist/private/reconnection/client_publish_engine_reconnection.d.ts +1 -1
- package/dist/private/reconnection/client_publish_engine_reconnection.js +54 -43
- package/dist/private/reconnection/client_publish_engine_reconnection.js.map +1 -1
- package/dist/private/reconnection/client_reconnection.d.ts +1 -1
- package/dist/private/reconnection/client_subscription_reconnection.d.ts +1 -1
- package/dist/private/reconnection/client_subscription_reconnection.js +2 -2
- package/dist/private/reconnection/client_subscription_reconnection.js.map +1 -1
- package/dist/private/reconnection/reconnection.d.ts +4 -4
- package/dist/private/reconnection/reconnection.js +200 -281
- package/dist/private/reconnection/reconnection.js.map +1 -1
- package/dist/tools/findservers.d.ts +7 -2
- package/dist/tools/findservers.js +41 -53
- package/dist/tools/findservers.js.map +1 -1
- package/dist/tools/read_history_server_capabilities.d.ts +1 -1
- package/dist/tools/read_history_server_capabilities.js +9 -8
- package/dist/tools/read_history_server_capabilities.js.map +1 -1
- package/dist/user_identity_info.d.ts +1 -1
- package/dist/verify.js.map +1 -1
- package/package.json +45 -45
- package/source/alarms_and_conditions/client_alarm_tools.ts +14 -8
- package/source/alarms_and_conditions/client_tools.ts +7 -6
- package/source/client_base.ts +93 -79
- package/source/client_monitored_item.ts +7 -8
- package/source/client_monitored_item_base.ts +12 -14
- package/source/client_monitored_item_group.ts +5 -5
- package/source/client_monitored_item_toolbox.ts +13 -14
- package/source/client_session.ts +37 -40
- package/source/client_session_keepalive_manager.ts +7 -10
- package/source/client_subscription.ts +11 -12
- package/source/client_utils.ts +6 -6
- package/source/common.ts +12 -12
- package/source/index.ts +44 -40
- package/source/opcua_client.ts +24 -23
- package/source/private/client_base_impl.ts +329 -290
- package/source/private/client_monitored_item_group_impl.ts +10 -14
- package/source/private/client_monitored_item_impl.ts +17 -17
- package/source/private/client_publish_engine.ts +11 -12
- package/source/private/client_session_impl.ts +85 -82
- package/source/private/client_subscription_impl.ts +42 -41
- package/source/private/i_private_client.ts +8 -8
- package/source/private/opcua_client_impl.ts +118 -97
- package/source/private/performance.ts +2 -3
- package/source/private/reconnection/client_publish_engine_reconnection.ts +76 -68
- package/source/private/reconnection/client_reconnection.ts +1 -1
- package/source/private/reconnection/client_subscription_reconnection.ts +16 -13
- package/source/private/reconnection/reconnection.ts +307 -301
- package/source/tools/findservers.ts +43 -62
- package/source/tools/read_history_server_capabilities.ts +20 -22
- package/source/user_identity_info.ts +5 -5
- package/source/verify.ts +25 -25
|
@@ -8,32 +8,35 @@ exports.ClientBaseImpl = void 0;
|
|
|
8
8
|
* @module node-opcua-client-private
|
|
9
9
|
*/
|
|
10
10
|
// tslint:disable:no-unused-expression
|
|
11
|
-
const
|
|
12
|
-
const
|
|
13
|
-
const async_1 = __importDefault(require("async"));
|
|
14
|
-
const chalk_1 = __importDefault(require("chalk"));
|
|
11
|
+
const node_fs_1 = __importDefault(require("node:fs"));
|
|
12
|
+
const node_path_1 = __importDefault(require("node:path"));
|
|
15
13
|
const global_mutex_1 = require("@ster5/global-mutex");
|
|
14
|
+
const chalk_1 = __importDefault(require("chalk"));
|
|
16
15
|
const node_opcua_assert_1 = require("node-opcua-assert");
|
|
16
|
+
const node_opcua_certificate_manager_1 = require("node-opcua-certificate-manager");
|
|
17
17
|
const node_opcua_common_1 = require("node-opcua-common");
|
|
18
18
|
const web_1 = require("node-opcua-crypto/web");
|
|
19
19
|
const node_opcua_date_time_1 = require("node-opcua-date-time");
|
|
20
20
|
const node_opcua_debug_1 = require("node-opcua-debug");
|
|
21
|
-
const node_opcua_common_2 = require("node-opcua-common");
|
|
22
21
|
const node_opcua_hostname_1 = require("node-opcua-hostname");
|
|
23
22
|
const node_opcua_secure_channel_1 = require("node-opcua-secure-channel");
|
|
24
23
|
const node_opcua_service_discovery_1 = require("node-opcua-service-discovery");
|
|
25
24
|
const node_opcua_service_endpoints_1 = require("node-opcua-service-endpoints");
|
|
26
25
|
const node_opcua_service_secure_channel_1 = require("node-opcua-service-secure-channel");
|
|
26
|
+
const node_opcua_service_session_1 = require("node-opcua-service-session");
|
|
27
27
|
const node_opcua_status_code_1 = require("node-opcua-status-code");
|
|
28
28
|
const node_opcua_utils_1 = require("node-opcua-utils");
|
|
29
|
-
const node_opcua_certificate_manager_1 = require("node-opcua-certificate-manager");
|
|
30
|
-
const node_opcua_service_session_1 = require("node-opcua-service-session");
|
|
31
29
|
const client_base_1 = require("../client_base");
|
|
32
30
|
const verify_1 = require("../verify");
|
|
33
31
|
const debugLog = (0, node_opcua_debug_1.make_debugLog)(__filename);
|
|
34
32
|
const doDebug = (0, node_opcua_debug_1.checkDebugFlag)(__filename);
|
|
35
33
|
const errorLog = (0, node_opcua_debug_1.make_errorLog)(__filename);
|
|
36
34
|
const warningLog = (0, node_opcua_debug_1.make_warningLog)(__filename);
|
|
35
|
+
function makeCertificateThumbPrint(certificate) {
|
|
36
|
+
if (!certificate)
|
|
37
|
+
return null;
|
|
38
|
+
return (0, web_1.makeSHA1Thumbprint)(Array.isArray(certificate) ? certificate[0] : certificate);
|
|
39
|
+
}
|
|
37
40
|
const traceInternalState = false;
|
|
38
41
|
const defaultConnectionStrategy = {
|
|
39
42
|
initialDelay: 1000,
|
|
@@ -55,7 +58,7 @@ function __findEndpoint(endpointUrl, params, _callback) {
|
|
|
55
58
|
};
|
|
56
59
|
const securityMode = params.securityMode;
|
|
57
60
|
const securityPolicy = params.securityPolicy;
|
|
58
|
-
const
|
|
61
|
+
const _connectionStrategy = params.connectionStrategy;
|
|
59
62
|
const options = {
|
|
60
63
|
applicationName: params.applicationName,
|
|
61
64
|
applicationUri: params.applicationUri,
|
|
@@ -74,10 +77,12 @@ function __findEndpoint(endpointUrl, params, _callback) {
|
|
|
74
77
|
masterClient._tmpClient = client;
|
|
75
78
|
let selectedEndpoint;
|
|
76
79
|
const allEndpoints = [];
|
|
77
|
-
const
|
|
78
|
-
(
|
|
80
|
+
const step1_connect = () => {
|
|
81
|
+
return new Promise((resolve, reject) => {
|
|
79
82
|
// rebind backoff handler
|
|
80
|
-
masterClient.listeners("backoff").forEach((handler) =>
|
|
83
|
+
masterClient.listeners("backoff").forEach((handler) => {
|
|
84
|
+
client.on("backoff", handler);
|
|
85
|
+
});
|
|
81
86
|
// c8 ignore next
|
|
82
87
|
if (doDebug) {
|
|
83
88
|
client.on("backoff", (retryCount, delay) => {
|
|
@@ -86,7 +91,6 @@ function __findEndpoint(endpointUrl, params, _callback) {
|
|
|
86
91
|
}
|
|
87
92
|
client.connect(endpointUrl, (err) => {
|
|
88
93
|
if (err) {
|
|
89
|
-
// let's improve the error message with meaningful info
|
|
90
94
|
err.message =
|
|
91
95
|
"Fail to connect to server at " +
|
|
92
96
|
endpointUrl +
|
|
@@ -95,19 +99,22 @@ function __findEndpoint(endpointUrl, params, _callback) {
|
|
|
95
99
|
err.message +
|
|
96
100
|
")";
|
|
97
101
|
warningLog(err.message);
|
|
102
|
+
return reject(err);
|
|
98
103
|
}
|
|
99
|
-
|
|
104
|
+
resolve();
|
|
100
105
|
});
|
|
101
|
-
}
|
|
102
|
-
|
|
106
|
+
});
|
|
107
|
+
};
|
|
108
|
+
const step2_getEndpoints = () => {
|
|
109
|
+
return new Promise((resolve, reject) => {
|
|
103
110
|
client.getEndpoints((err, endpoints) => {
|
|
104
111
|
if (err) {
|
|
105
|
-
err.message =
|
|
106
|
-
return
|
|
112
|
+
err.message = `error in getEndpoints \n${err.message}`;
|
|
113
|
+
return reject(err);
|
|
107
114
|
}
|
|
108
115
|
// c8 ignore next
|
|
109
116
|
if (!endpoints) {
|
|
110
|
-
return
|
|
117
|
+
return reject(new Error("Internal Error"));
|
|
111
118
|
}
|
|
112
119
|
for (const endpoint of endpoints) {
|
|
113
120
|
if (endpoint.securityMode === securityMode && endpoint.securityPolicyUri === securityPolicy) {
|
|
@@ -117,20 +124,19 @@ function __findEndpoint(endpointUrl, params, _callback) {
|
|
|
117
124
|
selectedEndpoint = endpoint; // found it
|
|
118
125
|
}
|
|
119
126
|
}
|
|
120
|
-
|
|
127
|
+
resolve();
|
|
121
128
|
});
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
}
|
|
129
|
+
});
|
|
130
|
+
};
|
|
131
|
+
const step3_disconnect = () => {
|
|
132
|
+
return new Promise((resolve) => {
|
|
133
|
+
client.disconnect(() => resolve());
|
|
134
|
+
});
|
|
135
|
+
};
|
|
136
|
+
step1_connect()
|
|
137
|
+
.then(() => step2_getEndpoints())
|
|
138
|
+
.then(() => step3_disconnect())
|
|
139
|
+
.then(() => {
|
|
134
140
|
if (!selectedEndpoint) {
|
|
135
141
|
return callback(new Error("Cannot find an Endpoint matching " +
|
|
136
142
|
" security mode: " +
|
|
@@ -142,11 +148,12 @@ function __findEndpoint(endpointUrl, params, _callback) {
|
|
|
142
148
|
if (doDebug) {
|
|
143
149
|
debugLog(chalk_1.default.bgWhite.red("xxxxxxxxxxxxxxxxxxxxx => selected EndPoint = "), selectedEndpoint.toString());
|
|
144
150
|
}
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
151
|
+
callback(null, { endpoints: allEndpoints, selectedEndpoint });
|
|
152
|
+
})
|
|
153
|
+
.catch((err) => {
|
|
154
|
+
client.disconnect(() => {
|
|
155
|
+
callback(err);
|
|
156
|
+
});
|
|
150
157
|
});
|
|
151
158
|
}
|
|
152
159
|
/**
|
|
@@ -161,9 +168,9 @@ async function _verify_serverCertificate(certificateManager, serverCertificate)
|
|
|
161
168
|
const status1 = await certificateManager.verifyCertificate(serverCertificate);
|
|
162
169
|
debugLog(status1);
|
|
163
170
|
}
|
|
164
|
-
warningLog("serverCertificate = ", (
|
|
171
|
+
warningLog("serverCertificate = ", makeCertificateThumbPrint(serverCertificate)?.toString("hex") || "none");
|
|
165
172
|
warningLog("serverCertificate = ", serverCertificate.toString("base64"));
|
|
166
|
-
throw new Error(
|
|
173
|
+
throw new Error(`server Certificate verification failed with err ${status?.toString()}`);
|
|
167
174
|
}
|
|
168
175
|
}
|
|
169
176
|
const forceEndpointDiscoveryOnConnect = !!parseInt(process.env.NODEOPCUA_CLIENT_FORCE_ENDPOINT_DISCOVERY || "0", 10);
|
|
@@ -225,7 +232,7 @@ class ClientBaseImpl extends node_opcua_common_1.OPCUASecureObject {
|
|
|
225
232
|
* true if the client is trying to reconnect to the server after a connection break.
|
|
226
233
|
*/
|
|
227
234
|
get isReconnecting() {
|
|
228
|
-
return (!!
|
|
235
|
+
return (!!this._secureChannel?.isConnecting ||
|
|
229
236
|
this._internalState === "reconnecting_newchannel_connected" ||
|
|
230
237
|
this._internalState === "reconnecting");
|
|
231
238
|
}
|
|
@@ -304,6 +311,7 @@ class ClientBaseImpl extends node_opcua_common_1.OPCUASecureObject {
|
|
|
304
311
|
if (doDebug) {
|
|
305
312
|
debugLog(chalk_1.default.cyan(` Client ${this._instanceNumber} ${this.clientName} emitting `), chalk_1.default.magentaBright(eventName));
|
|
306
313
|
}
|
|
314
|
+
// @ts-expect-error
|
|
307
315
|
return super.emit(eventName, ...others);
|
|
308
316
|
}
|
|
309
317
|
constructor(options) {
|
|
@@ -313,7 +321,7 @@ class ClientBaseImpl extends node_opcua_common_1.OPCUASecureObject {
|
|
|
313
321
|
}
|
|
314
322
|
options.privateKeyFile = options.privateKeyFile || options.clientCertificateManager.privateKey;
|
|
315
323
|
options.certificateFile =
|
|
316
|
-
options.certificateFile ||
|
|
324
|
+
options.certificateFile || node_path_1.default.join(options.clientCertificateManager.rootDir, "own/certs/client_certificate.pem");
|
|
317
325
|
super(options);
|
|
318
326
|
this._setInternalState("uninitialized");
|
|
319
327
|
this._instanceNumber = g_ClientCounter++;
|
|
@@ -335,7 +343,7 @@ class ClientBaseImpl extends node_opcua_common_1.OPCUASecureObject {
|
|
|
335
343
|
this.defaultSecureTokenLifetime = options.defaultSecureTokenLifetime || 600000;
|
|
336
344
|
this.defaultTransactionTimeout = options.defaultTransactionTimeout;
|
|
337
345
|
this.tokenRenewalInterval = options.tokenRenewalInterval || 0;
|
|
338
|
-
(0, node_opcua_assert_1.assert)(isFinite(this.tokenRenewalInterval) && this.tokenRenewalInterval >= 0);
|
|
346
|
+
(0, node_opcua_assert_1.assert)(Number.isFinite(this.tokenRenewalInterval) && this.tokenRenewalInterval >= 0);
|
|
339
347
|
this.securityMode = (0, node_opcua_service_secure_channel_1.coerceMessageSecurityMode)(options.securityMode);
|
|
340
348
|
this.securityPolicy = (0, node_opcua_secure_channel_1.coerceSecurityPolicy)(options.securityPolicy);
|
|
341
349
|
this.serverCertificate = options.serverCertificate;
|
|
@@ -375,15 +383,13 @@ class ClientBaseImpl extends node_opcua_common_1.OPCUASecureObject {
|
|
|
375
383
|
this._secureChannel = null;
|
|
376
384
|
callback();
|
|
377
385
|
});
|
|
378
|
-
this.once("reconnection_canceled", () => {
|
|
379
|
-
/* empty */
|
|
380
|
-
});
|
|
381
386
|
}
|
|
382
387
|
_recreate_secure_channel(callback) {
|
|
383
388
|
debugLog("_recreate_secure_channel... while internalState is", this._internalState);
|
|
384
389
|
if (!this.knowsServerEndpoint) {
|
|
385
390
|
debugLog("Cannot reconnect , server endpoint is unknown");
|
|
386
|
-
|
|
391
|
+
callback(new Error("Cannot reconnect, server endpoint is unknown - this.knowsServerEndpoint = false"));
|
|
392
|
+
return;
|
|
387
393
|
}
|
|
388
394
|
(0, node_opcua_assert_1.assert)(this.knowsServerEndpoint);
|
|
389
395
|
this._setInternalState("reconnecting");
|
|
@@ -400,7 +406,7 @@ class ClientBaseImpl extends node_opcua_common_1.OPCUASecureObject {
|
|
|
400
406
|
const _when_reconnectionIsCanceled = (callback) => {
|
|
401
407
|
doDebug && debugLog("attempt to recreate a new secure channel : suspended because reconnection is canceled !");
|
|
402
408
|
this.emit("reconnection_canceled");
|
|
403
|
-
return callback(new Error(
|
|
409
|
+
return callback(new Error(`Reconnection has been canceled - ${this.clientName}`));
|
|
404
410
|
};
|
|
405
411
|
const _failAndRetry = (err, message, callback) => {
|
|
406
412
|
debugLog("failAndRetry; ", message);
|
|
@@ -442,17 +448,18 @@ class ClientBaseImpl extends node_opcua_common_1.OPCUASecureObject {
|
|
|
442
448
|
return _when_internal_error(err, callback);
|
|
443
449
|
}
|
|
444
450
|
if (err.message.match(/ECONNREFUSED|ECONNABORTED|ETIMEDOUT/)) {
|
|
445
|
-
return _failAndRetry(err,
|
|
451
|
+
return _failAndRetry(err, `create secure channel failed with ECONNREFUSED|ECONNABORTED|ETIMEDOUT\n${err.message}`, callback);
|
|
446
452
|
}
|
|
447
453
|
if (err.message.match("Backoff aborted.")) {
|
|
448
|
-
|
|
454
|
+
_failAndRetry(err, "cannot create secure channel (backoff aborted)", callback);
|
|
455
|
+
return;
|
|
449
456
|
}
|
|
450
|
-
if (err
|
|
451
|
-
err
|
|
452
|
-
// it is possible also that hte server has shutdown innapropriately the connection
|
|
457
|
+
if (err?.message.match("BadCertificateInvalid") ||
|
|
458
|
+
err?.message.match(/socket has been disconnected by third party/)) {
|
|
459
|
+
// it is possible also that hte server has shutdown innapropriately the connection
|
|
453
460
|
warningLog("the server certificate has changed, we need to retrieve server certificate again: ", err.message);
|
|
454
461
|
const oldServerCertificate = this.serverCertificate;
|
|
455
|
-
warningLog("old server certificate ",
|
|
462
|
+
warningLog("old server certificate ", makeCertificateThumbPrint(oldServerCertificate)?.toString("hex") || "undefined");
|
|
456
463
|
// the server may have shut down the channel because its certificate
|
|
457
464
|
// has changed ....
|
|
458
465
|
// let request the server certificate again ....
|
|
@@ -461,9 +468,9 @@ class ClientBaseImpl extends node_opcua_common_1.OPCUASecureObject {
|
|
|
461
468
|
return _failAndRetry(err1, "Failing to fetch new server certificate", callback);
|
|
462
469
|
}
|
|
463
470
|
const newServerCertificate = this.serverCertificate;
|
|
464
|
-
warningLog("new server certificate ", (
|
|
465
|
-
const sha1Old = oldServerCertificate
|
|
466
|
-
const sha1New = newServerCertificate
|
|
471
|
+
warningLog("new server certificate ", makeCertificateThumbPrint(newServerCertificate)?.toString("hex") || "none");
|
|
472
|
+
const sha1Old = makeCertificateThumbPrint(oldServerCertificate)?.toString("hex") || null;
|
|
473
|
+
const sha1New = makeCertificateThumbPrint(newServerCertificate)?.toString("hex") || null;
|
|
467
474
|
if (sha1Old === sha1New) {
|
|
468
475
|
warningLog("server certificate has not changed, but was expected to have changed");
|
|
469
476
|
return _failAndRetry(new Error("Server Certificate not changed"), "Failing to fetch new server certificate", callback);
|
|
@@ -514,61 +521,66 @@ class ClientBaseImpl extends node_opcua_common_1.OPCUASecureObject {
|
|
|
514
521
|
secureChannel.protocolVersion = this.protocolVersion;
|
|
515
522
|
this._secureChannel = secureChannel;
|
|
516
523
|
this.emit("secure_channel_created", secureChannel);
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
(innerCallback) => {
|
|
524
|
+
const step2_openSecureChannel = () => {
|
|
525
|
+
return new Promise((resolve, reject) => {
|
|
520
526
|
debugLog("_internal_create_secure_channel before secureChannel.create");
|
|
521
527
|
secureChannel.create(this.endpointUrl, (err) => {
|
|
522
528
|
debugLog("_internal_create_secure_channel after secureChannel.create");
|
|
523
529
|
if (!this._secureChannel) {
|
|
524
530
|
debugLog("_secureChannel has been closed during the transaction !");
|
|
525
|
-
return
|
|
531
|
+
return reject(new Error("Secure Channel Closed"));
|
|
526
532
|
}
|
|
527
|
-
if (
|
|
528
|
-
|
|
533
|
+
if (err) {
|
|
534
|
+
return reject(err);
|
|
529
535
|
}
|
|
530
|
-
|
|
536
|
+
this._install_secure_channel_event_handlers(secureChannel);
|
|
537
|
+
resolve();
|
|
531
538
|
});
|
|
532
|
-
}
|
|
533
|
-
|
|
534
|
-
|
|
539
|
+
});
|
|
540
|
+
};
|
|
541
|
+
const step3_getEndpoints = () => {
|
|
542
|
+
return new Promise((resolve, reject) => {
|
|
535
543
|
(0, node_opcua_assert_1.assert)(this._secureChannel !== null);
|
|
536
544
|
if (!this.knowsServerEndpoint) {
|
|
537
545
|
this._setInternalState("connecting");
|
|
538
546
|
this.getEndpoints((err /*, endpoints?: EndpointDescription[]*/) => {
|
|
539
547
|
if (!this._secureChannel) {
|
|
540
548
|
debugLog("_secureChannel has been closed during the transaction ! (while getEndpoints)");
|
|
541
|
-
return
|
|
549
|
+
return reject(new Error("Secure Channel Closed"));
|
|
550
|
+
}
|
|
551
|
+
if (err) {
|
|
552
|
+
return reject(err);
|
|
542
553
|
}
|
|
543
|
-
|
|
554
|
+
resolve();
|
|
544
555
|
});
|
|
545
556
|
}
|
|
546
557
|
else {
|
|
547
558
|
// end points are already known
|
|
548
|
-
|
|
559
|
+
resolve();
|
|
549
560
|
}
|
|
550
|
-
}
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
+
});
|
|
562
|
+
};
|
|
563
|
+
step2_openSecureChannel()
|
|
564
|
+
.then(() => step3_getEndpoints())
|
|
565
|
+
.then(() => {
|
|
566
|
+
(0, node_opcua_assert_1.assert)(this._secureChannel !== null);
|
|
567
|
+
callback(null, secureChannel);
|
|
568
|
+
})
|
|
569
|
+
.catch((err) => {
|
|
570
|
+
doDebug && debugLog(this.clientName, " : Inner create secure channel has failed", err.message);
|
|
571
|
+
if (this._secureChannel) {
|
|
572
|
+
this._secureChannel.abortConnection(() => {
|
|
573
|
+
this._destroy_secure_channel();
|
|
561
574
|
callback(err);
|
|
562
|
-
}
|
|
575
|
+
});
|
|
563
576
|
}
|
|
564
577
|
else {
|
|
565
|
-
(
|
|
566
|
-
callback(null, secureChannel);
|
|
578
|
+
callback(err);
|
|
567
579
|
}
|
|
568
580
|
});
|
|
569
581
|
}
|
|
570
582
|
static async createCertificate(clientCertificateManager, certificateFile, applicationName, applicationUri) {
|
|
571
|
-
if (!
|
|
583
|
+
if (!node_fs_1.default.existsSync(certificateFile)) {
|
|
572
584
|
const hostname = (0, node_opcua_hostname_1.getHostname)();
|
|
573
585
|
// this.serverInfo.applicationUri!;
|
|
574
586
|
await clientCertificateManager.createSelfSignedCertificate({
|
|
@@ -582,8 +594,8 @@ class ClientBaseImpl extends node_opcua_common_1.OPCUASecureObject {
|
|
|
582
594
|
});
|
|
583
595
|
}
|
|
584
596
|
// c8 ignore next
|
|
585
|
-
if (!
|
|
586
|
-
throw new Error(
|
|
597
|
+
if (!node_fs_1.default.existsSync(certificateFile)) {
|
|
598
|
+
throw new Error(` cannot locate certificate file ${certificateFile}`);
|
|
587
599
|
}
|
|
588
600
|
}
|
|
589
601
|
async createDefaultCertificate() {
|
|
@@ -593,7 +605,7 @@ class ClientBaseImpl extends node_opcua_common_1.OPCUASecureObject {
|
|
|
593
605
|
}
|
|
594
606
|
this._inCreateDefaultCertificate = true;
|
|
595
607
|
if (!(0, node_opcua_utils_1.checkFileExistsAndIsNotEmpty)(this.certificateFile)) {
|
|
596
|
-
await (0, global_mutex_1.withLock)({ fileToLock: this.certificateFile
|
|
608
|
+
await (0, global_mutex_1.withLock)({ fileToLock: `${this.certificateFile}.mutex` }, async () => {
|
|
597
609
|
if ((0, node_opcua_utils_1.checkFileExistsAndIsNotEmpty)(this.certificateFile)) {
|
|
598
610
|
// the file may have been created in between
|
|
599
611
|
return;
|
|
@@ -603,15 +615,15 @@ class ClientBaseImpl extends node_opcua_common_1.OPCUASecureObject {
|
|
|
603
615
|
debugLog("privateKey = ", this.privateKeyFile);
|
|
604
616
|
debugLog(" = ", this.clientCertificateManager.privateKey);
|
|
605
617
|
debugLog("certificateFile = ", this.certificateFile);
|
|
606
|
-
const
|
|
607
|
-
const
|
|
618
|
+
const _certificate = this.getCertificate();
|
|
619
|
+
const _privateKey = this.getPrivateKey();
|
|
608
620
|
});
|
|
609
621
|
}
|
|
610
622
|
this._inCreateDefaultCertificate = false;
|
|
611
623
|
}
|
|
612
624
|
_getBuiltApplicationUri() {
|
|
613
625
|
if (!this._applicationUri) {
|
|
614
|
-
this._applicationUri = (0,
|
|
626
|
+
this._applicationUri = (0, node_opcua_common_1.makeApplicationUrn)((0, node_opcua_hostname_1.getHostname)(), this.applicationName);
|
|
615
627
|
}
|
|
616
628
|
return this._applicationUri;
|
|
617
629
|
}
|
|
@@ -627,8 +639,8 @@ class ClientBaseImpl extends node_opcua_common_1.OPCUASecureObject {
|
|
|
627
639
|
await this.clientCertificateManager.initialize();
|
|
628
640
|
await this.createDefaultCertificate();
|
|
629
641
|
// c8 ignore next
|
|
630
|
-
if (!
|
|
631
|
-
throw new Error(
|
|
642
|
+
if (!node_fs_1.default.existsSync(this.privateKeyFile)) {
|
|
643
|
+
throw new Error(` cannot locate private key file ${this.privateKeyFile}`);
|
|
632
644
|
}
|
|
633
645
|
if (this.isUnusable())
|
|
634
646
|
return;
|
|
@@ -643,13 +655,13 @@ class ClientBaseImpl extends node_opcua_common_1.OPCUASecureObject {
|
|
|
643
655
|
debugLog(err.message);
|
|
644
656
|
this.emit("connection_failed", err);
|
|
645
657
|
this._setInternalState("disconnected");
|
|
646
|
-
|
|
658
|
+
callback(err);
|
|
647
659
|
}
|
|
648
660
|
_handleDisconnectionWhileConnecting(err, callback) {
|
|
649
661
|
debugLog(err.message);
|
|
650
662
|
this.emit("connection_failed", err);
|
|
651
663
|
this._setInternalState("disconnected");
|
|
652
|
-
|
|
664
|
+
callback(err);
|
|
653
665
|
}
|
|
654
666
|
_handleSuccessfulConnection(callback) {
|
|
655
667
|
debugLog(" Connected successfully to ", this.endpointUrl);
|
|
@@ -662,7 +674,7 @@ class ClientBaseImpl extends node_opcua_common_1.OPCUASecureObject {
|
|
|
662
674
|
const callback = args[1];
|
|
663
675
|
(0, node_opcua_assert_1.assert)(typeof callback === "function", "expecting a callback");
|
|
664
676
|
if (typeof endpointUrl !== "string" || endpointUrl.length <= 0) {
|
|
665
|
-
errorLog(
|
|
677
|
+
errorLog(`[NODE-OPCUA-E03] OPCUAClient#connect expects a valid endpoint : ${endpointUrl}`);
|
|
666
678
|
callback(new Error("Invalid endpoint"));
|
|
667
679
|
return;
|
|
668
680
|
}
|
|
@@ -696,7 +708,7 @@ class ClientBaseImpl extends node_opcua_common_1.OPCUASecureObject {
|
|
|
696
708
|
}
|
|
697
709
|
if (forceEndpointDiscoveryOnConnect) {
|
|
698
710
|
debugLog("connecting with adjusted endpoint : ", adjustedEndpointUrl, " was =", endpointUrl);
|
|
699
|
-
this._connectStep2(adjustedEndpointUrl, callback);
|
|
711
|
+
this._connectStep2(adjustedEndpointUrl || "", callback);
|
|
700
712
|
}
|
|
701
713
|
else {
|
|
702
714
|
debugLog("connecting with endpoint : ", endpointUrl);
|
|
@@ -734,15 +746,13 @@ class ClientBaseImpl extends node_opcua_common_1.OPCUASecureObject {
|
|
|
734
746
|
}
|
|
735
747
|
debugLog(chalk_1.default.red("SecureChannel creation has failed with error :", err.message));
|
|
736
748
|
if (err.message.match(/ECONNABORTED/)) {
|
|
737
|
-
debugLog(chalk_1.default.yellow(
|
|
749
|
+
debugLog(chalk_1.default.yellow(`- The client cannot to :${endpointUrl}. Connection has been aborted.`));
|
|
738
750
|
err = new Error("The connection has been aborted");
|
|
739
751
|
this._handleUnrecoverableConnectionFailure(err, callback);
|
|
740
752
|
}
|
|
741
753
|
else if (err.message.match(/ECONNREF/)) {
|
|
742
|
-
debugLog(chalk_1.default.yellow(
|
|
743
|
-
err = new Error(
|
|
744
|
-
endpointUrl +
|
|
745
|
-
" .\n" +
|
|
754
|
+
debugLog(chalk_1.default.yellow(`- The client cannot to :${endpointUrl}. Server is not reachable.`));
|
|
755
|
+
err = new Error(`The connection cannot be established with server ${endpointUrl} .\n` +
|
|
746
756
|
"Please check that the server is up and running or your network configuration.\n" +
|
|
747
757
|
"Err = (" +
|
|
748
758
|
err.message +
|
|
@@ -754,7 +764,7 @@ class ClientBaseImpl extends node_opcua_common_1.OPCUASecureObject {
|
|
|
754
764
|
this._handleDisconnectionWhileConnecting(err, callback);
|
|
755
765
|
}
|
|
756
766
|
else {
|
|
757
|
-
err = new Error(
|
|
767
|
+
err = new Error(`The connection may have been rejected by server,\n Err = (${err.message})`);
|
|
758
768
|
this._handleUnrecoverableConnectionFailure(err, callback);
|
|
759
769
|
}
|
|
760
770
|
}
|
|
@@ -764,16 +774,18 @@ class ClientBaseImpl extends node_opcua_common_1.OPCUASecureObject {
|
|
|
764
774
|
if (!this._secureChannel) {
|
|
765
775
|
// this may happen if the Server has closed the connection abruptly for some unknown reason
|
|
766
776
|
// or if the tcp connection has been broken.
|
|
767
|
-
|
|
777
|
+
callback(new Error("performMessageTransaction: No SecureChannel , connection may have been canceled abruptly by server"));
|
|
778
|
+
return;
|
|
768
779
|
}
|
|
769
780
|
if (this._internalState !== "connected" &&
|
|
770
781
|
this._internalState !== "reconnecting_newchannel_connected" &&
|
|
771
782
|
this._internalState !== "connecting" &&
|
|
772
783
|
this._internalState !== "reconnecting") {
|
|
773
|
-
|
|
784
|
+
callback(new Error("performMessageTransaction: Invalid client state = " +
|
|
774
785
|
this._internalState +
|
|
775
786
|
" while performing a transaction " +
|
|
776
787
|
request.schema.name));
|
|
788
|
+
return;
|
|
777
789
|
}
|
|
778
790
|
(0, node_opcua_assert_1.assert)(this._secureChannel);
|
|
779
791
|
(0, node_opcua_assert_1.assert)(request);
|
|
@@ -812,7 +824,8 @@ class ClientBaseImpl extends node_opcua_common_1.OPCUASecureObject {
|
|
|
812
824
|
}
|
|
813
825
|
getEndpoints(...args) {
|
|
814
826
|
if (args.length === 1) {
|
|
815
|
-
|
|
827
|
+
this.getEndpoints({}, args[0]);
|
|
828
|
+
return;
|
|
816
829
|
}
|
|
817
830
|
const options = args[0];
|
|
818
831
|
const callback = args[1];
|
|
@@ -829,29 +842,36 @@ class ClientBaseImpl extends node_opcua_common_1.OPCUASecureObject {
|
|
|
829
842
|
});
|
|
830
843
|
this.performMessageTransaction(request, (err, response) => {
|
|
831
844
|
if (err) {
|
|
832
|
-
|
|
845
|
+
callback(err);
|
|
846
|
+
return;
|
|
833
847
|
}
|
|
834
848
|
this._serverEndpoints = [];
|
|
835
849
|
// c8 ignore next
|
|
836
850
|
if (!response || !(response instanceof node_opcua_service_endpoints_1.GetEndpointsResponse)) {
|
|
837
|
-
|
|
851
|
+
callback(new Error("Internal Error"));
|
|
852
|
+
return;
|
|
838
853
|
}
|
|
839
|
-
if (response
|
|
854
|
+
if (response?.endpoints) {
|
|
840
855
|
this._serverEndpoints = response.endpoints;
|
|
841
856
|
}
|
|
842
857
|
callback(null, this._serverEndpoints);
|
|
843
858
|
});
|
|
859
|
+
return;
|
|
844
860
|
}
|
|
845
861
|
/**
|
|
846
862
|
* @deprecated
|
|
847
863
|
*/
|
|
848
864
|
getEndpointsRequest(options, callback) {
|
|
849
865
|
warningLog("note: ClientBaseImpl#getEndpointsRequest is deprecated, use ClientBaseImpl#getEndpoints instead");
|
|
850
|
-
|
|
866
|
+
this.getEndpoints(options, callback);
|
|
851
867
|
}
|
|
852
868
|
findServers(...args) {
|
|
853
869
|
if (args.length === 1) {
|
|
854
|
-
|
|
870
|
+
if (typeof args[0] === "function") {
|
|
871
|
+
this.findServers({}, args[0]);
|
|
872
|
+
return;
|
|
873
|
+
}
|
|
874
|
+
throw new Error("Invalid arguments");
|
|
855
875
|
}
|
|
856
876
|
const options = args[0];
|
|
857
877
|
const callback = args[1];
|
|
@@ -862,39 +882,46 @@ class ClientBaseImpl extends node_opcua_common_1.OPCUASecureObject {
|
|
|
862
882
|
});
|
|
863
883
|
this.performMessageTransaction(request, (err, response) => {
|
|
864
884
|
if (err) {
|
|
865
|
-
|
|
885
|
+
callback(err);
|
|
886
|
+
return;
|
|
866
887
|
}
|
|
867
888
|
/* c8 ignore next */
|
|
868
889
|
if (!response || !(response instanceof node_opcua_service_discovery_1.FindServersResponse)) {
|
|
869
|
-
|
|
890
|
+
callback(new Error("Internal Error"));
|
|
891
|
+
return;
|
|
870
892
|
}
|
|
871
893
|
response.servers = response.servers || [];
|
|
872
894
|
callback(null, response.servers);
|
|
873
895
|
});
|
|
896
|
+
return undefined;
|
|
874
897
|
}
|
|
875
898
|
findServersOnNetwork(...args) {
|
|
876
899
|
if (args.length === 1) {
|
|
877
|
-
|
|
900
|
+
this.findServersOnNetwork({}, args[0]);
|
|
901
|
+
return undefined;
|
|
878
902
|
}
|
|
879
903
|
const options = args[0];
|
|
880
904
|
const callback = args[1];
|
|
881
905
|
const request = new node_opcua_service_discovery_1.FindServersOnNetworkRequest(options);
|
|
882
906
|
this.performMessageTransaction(request, (err, response) => {
|
|
883
907
|
if (err) {
|
|
884
|
-
|
|
908
|
+
callback(err);
|
|
909
|
+
return;
|
|
885
910
|
}
|
|
886
911
|
/* c8 ignore next */
|
|
887
912
|
if (!response || !(response instanceof node_opcua_service_discovery_1.FindServersOnNetworkResponse)) {
|
|
888
|
-
|
|
913
|
+
callback(new Error("Internal Error"));
|
|
914
|
+
return;
|
|
889
915
|
}
|
|
890
916
|
response.servers = response.servers || [];
|
|
891
917
|
callback(null, response.servers);
|
|
892
918
|
});
|
|
919
|
+
return undefined;
|
|
893
920
|
}
|
|
894
921
|
_removeSession(session) {
|
|
895
922
|
const index = this._sessions.indexOf(session);
|
|
896
923
|
if (index >= 0) {
|
|
897
|
-
const
|
|
924
|
+
const _s = this._sessions.splice(index, 1)[0];
|
|
898
925
|
// assert(s === session);
|
|
899
926
|
// assert(session._client === this);
|
|
900
927
|
session._client = null;
|
|
@@ -925,23 +952,19 @@ class ClientBaseImpl extends node_opcua_common_1.OPCUASecureObject {
|
|
|
925
952
|
}
|
|
926
953
|
});
|
|
927
954
|
}
|
|
928
|
-
closeSession(
|
|
929
|
-
const session = args[0];
|
|
930
|
-
const deleteSubscriptions = args[1];
|
|
931
|
-
const callback = args[2];
|
|
955
|
+
closeSession(session, deleteSubscriptions, callback) {
|
|
932
956
|
(0, node_opcua_assert_1.assert)(typeof deleteSubscriptions === "boolean");
|
|
933
|
-
(0, node_opcua_assert_1.assert)(typeof callback === "function");
|
|
934
957
|
(0, node_opcua_assert_1.assert)(session);
|
|
935
958
|
(0, node_opcua_assert_1.assert)(session._client === this, "session must be attached to this");
|
|
936
959
|
session._closed = true;
|
|
937
960
|
// todo : send close session on secure channel
|
|
938
|
-
this._closeSession(session, deleteSubscriptions, (err,
|
|
961
|
+
this._closeSession(session, deleteSubscriptions, (err, _response) => {
|
|
939
962
|
session.emitCloseEvent(node_opcua_status_code_1.StatusCodes.Good);
|
|
940
963
|
this._removeSession(session);
|
|
941
964
|
session.dispose();
|
|
942
965
|
(0, node_opcua_assert_1.assert)(this._sessions.indexOf(session) === -1);
|
|
943
966
|
(0, node_opcua_assert_1.assert)(session._closed, "session must indicate it is closed");
|
|
944
|
-
callback(err ? err : undefined);
|
|
967
|
+
callback?.(err ? err : undefined);
|
|
945
968
|
});
|
|
946
969
|
}
|
|
947
970
|
// eslint-disable-next-line max-statements
|
|
@@ -951,12 +974,12 @@ class ClientBaseImpl extends node_opcua_common_1.OPCUASecureObject {
|
|
|
951
974
|
this._reconnectionIsCanceled = true;
|
|
952
975
|
if (this._tmpClient) {
|
|
953
976
|
warningLog("disconnecting client while tmpClient exists", this._tmpClient.clientName);
|
|
954
|
-
this._tmpClient.disconnect((
|
|
977
|
+
this._tmpClient.disconnect((_err) => {
|
|
955
978
|
this._tmpClient = undefined;
|
|
956
979
|
// retry disconnect on main client
|
|
957
980
|
this.disconnect(callback);
|
|
958
981
|
});
|
|
959
|
-
return;
|
|
982
|
+
return undefined;
|
|
960
983
|
}
|
|
961
984
|
if (this._internalState === "disconnected" || this._internalState === "disconnecting") {
|
|
962
985
|
if (this._internalState === "disconnecting") {
|
|
@@ -965,7 +988,8 @@ class ClientBaseImpl extends node_opcua_common_1.OPCUASecureObject {
|
|
|
965
988
|
if (!this._reconnectionIsCanceled && this.isReconnecting) {
|
|
966
989
|
errorLog("Internal Error : _reconnectionIsCanceled should be true if isReconnecting is true");
|
|
967
990
|
}
|
|
968
|
-
|
|
991
|
+
callback();
|
|
992
|
+
return undefined;
|
|
969
993
|
}
|
|
970
994
|
debugLog("disconnecting client! (will set reconnectionIsCanceled to true");
|
|
971
995
|
this._reconnectionIsCanceled = true;
|
|
@@ -979,7 +1003,7 @@ class ClientBaseImpl extends node_opcua_common_1.OPCUASecureObject {
|
|
|
979
1003
|
// sessions cannot be cancelled properly and must be discarded.
|
|
980
1004
|
this.disconnect(callback);
|
|
981
1005
|
});
|
|
982
|
-
return;
|
|
1006
|
+
return undefined;
|
|
983
1007
|
}
|
|
984
1008
|
if (this._sessions.length && !this.keepPendingSessionsOnDisconnect) {
|
|
985
1009
|
debugLog("warning : disconnection : closing pending sessions");
|
|
@@ -988,7 +1012,7 @@ class ClientBaseImpl extends node_opcua_common_1.OPCUASecureObject {
|
|
|
988
1012
|
this._close_pending_sessions(( /*err*/) => {
|
|
989
1013
|
this.disconnect(callback);
|
|
990
1014
|
});
|
|
991
|
-
return;
|
|
1015
|
+
return undefined;
|
|
992
1016
|
}
|
|
993
1017
|
debugLog("Disconnecting !");
|
|
994
1018
|
this._setInternalState("disconnecting");
|
|
@@ -1030,6 +1054,7 @@ class ClientBaseImpl extends node_opcua_common_1.OPCUASecureObject {
|
|
|
1030
1054
|
// this.emit("close", null);
|
|
1031
1055
|
callback();
|
|
1032
1056
|
}
|
|
1057
|
+
return undefined;
|
|
1033
1058
|
}
|
|
1034
1059
|
// override me !
|
|
1035
1060
|
_on_connection_reestablished(callback) {
|
|
@@ -1037,35 +1062,32 @@ class ClientBaseImpl extends node_opcua_common_1.OPCUASecureObject {
|
|
|
1037
1062
|
}
|
|
1038
1063
|
toString() {
|
|
1039
1064
|
let str = "\n";
|
|
1040
|
-
str +=
|
|
1041
|
-
str +=
|
|
1042
|
-
str +=
|
|
1043
|
-
str +=
|
|
1044
|
-
str +=
|
|
1045
|
-
" server certificate fingerprint " +
|
|
1046
|
-
(this.serverCertificate ? (0, web_1.makeSHA1Thumbprint)(this.serverCertificate).toString("hex") : "") +
|
|
1047
|
-
"\n";
|
|
1065
|
+
str += ` defaultSecureTokenLifetime.... ${this.defaultSecureTokenLifetime}\n`;
|
|
1066
|
+
str += ` securityMode.................. ${node_opcua_service_secure_channel_1.MessageSecurityMode[this.securityMode]}\n`;
|
|
1067
|
+
str += ` securityPolicy................ ${this.securityPolicy.toString()}\n`;
|
|
1068
|
+
str += ` certificate fingerprint....... ${makeCertificateThumbPrint(this.getCertificate())?.toString("hex") || "none"}\n`;
|
|
1069
|
+
str += ` server certificate fingerprint ${makeCertificateThumbPrint(this.serverCertificate)?.toString("hex") || "none"}\n`;
|
|
1048
1070
|
// this.serverCertificate = options.serverCertificate || null + "\n";
|
|
1049
|
-
str +=
|
|
1050
|
-
str +=
|
|
1051
|
-
str +=
|
|
1052
|
-
str +=
|
|
1053
|
-
str +=
|
|
1071
|
+
str += ` keepSessionAlive.............. ${this.keepSessionAlive}\n`;
|
|
1072
|
+
str += ` bytesRead..................... ${this.bytesRead}\n`;
|
|
1073
|
+
str += ` bytesWritten.................. ${this.bytesWritten}\n`;
|
|
1074
|
+
str += ` transactionsPerformed......... ${this.transactionsPerformed}\n`;
|
|
1075
|
+
str += ` timedOutRequestCount.......... ${this.timedOutRequestCount}\n`;
|
|
1054
1076
|
str += " connectionStrategy." + "\n";
|
|
1055
|
-
str +=
|
|
1056
|
-
str +=
|
|
1057
|
-
str +=
|
|
1058
|
-
str +=
|
|
1059
|
-
str +=
|
|
1060
|
-
str +=
|
|
1061
|
-
str +=
|
|
1062
|
-
str +=
|
|
1063
|
-
str +=
|
|
1064
|
-
str +=
|
|
1065
|
-
str +=
|
|
1066
|
-
str +=
|
|
1077
|
+
str += ` .maxRetry............... ${this.connectionStrategy.maxRetry}\n`;
|
|
1078
|
+
str += ` .initialDelay........... ${this.connectionStrategy.initialDelay}\n`;
|
|
1079
|
+
str += ` .maxDelay............... ${this.connectionStrategy.maxDelay}\n`;
|
|
1080
|
+
str += ` .randomisationFactor.... ${this.connectionStrategy.randomisationFactor}\n`;
|
|
1081
|
+
str += ` keepSessionAlive.............. ${this.keepSessionAlive}\n`;
|
|
1082
|
+
str += ` applicationName............... ${this.applicationName}\n`;
|
|
1083
|
+
str += ` applicationUri................ ${this._getBuiltApplicationUri()}\n`;
|
|
1084
|
+
str += ` clientName.................... ${this.clientName}\n`;
|
|
1085
|
+
str += ` reconnectOnFailure............ ${this.reconnectOnFailure}\n`;
|
|
1086
|
+
str += ` isReconnecting................ ${this.isReconnecting}\n`;
|
|
1087
|
+
str += ` (internal state).............. ${this._internalState}\n`;
|
|
1088
|
+
str += ` sessions count................ ${this.getSessions().length}\n`;
|
|
1067
1089
|
if (this._secureChannel) {
|
|
1068
|
-
str +=
|
|
1090
|
+
str += `secureChannel:\n${this._secureChannel.toString()}`;
|
|
1069
1091
|
}
|
|
1070
1092
|
return str;
|
|
1071
1093
|
}
|
|
@@ -1073,7 +1095,7 @@ class ClientBaseImpl extends node_opcua_common_1.OPCUASecureObject {
|
|
|
1073
1095
|
return this._sessions;
|
|
1074
1096
|
}
|
|
1075
1097
|
getTransportSettings() {
|
|
1076
|
-
return this._secureChannel
|
|
1098
|
+
return this._secureChannel?.getTransportSettings() || {};
|
|
1077
1099
|
}
|
|
1078
1100
|
_addSession(session) {
|
|
1079
1101
|
(0, node_opcua_assert_1.assert)(!session._client || session._client === this);
|
|
@@ -1114,14 +1136,16 @@ class ClientBaseImpl extends node_opcua_common_1.OPCUASecureObject {
|
|
|
1114
1136
|
privateKeyFile,
|
|
1115
1137
|
clientCertificateManager: this.clientCertificateManager
|
|
1116
1138
|
};
|
|
1117
|
-
|
|
1139
|
+
__findEndpoint.call(this, discoveryUrl, params, (err, result) => {
|
|
1118
1140
|
if (err) {
|
|
1119
|
-
|
|
1141
|
+
callback(err);
|
|
1142
|
+
return;
|
|
1120
1143
|
}
|
|
1121
1144
|
// c8 ignore next
|
|
1122
1145
|
if (!result) {
|
|
1123
1146
|
const err1 = new Error("internal error");
|
|
1124
|
-
|
|
1147
|
+
callback(err1);
|
|
1148
|
+
return;
|
|
1125
1149
|
}
|
|
1126
1150
|
const endpoint = result.selectedEndpoint;
|
|
1127
1151
|
if (!endpoint) {
|
|
@@ -1130,23 +1154,24 @@ class ClientBaseImpl extends node_opcua_common_1.OPCUASecureObject {
|
|
|
1130
1154
|
node_opcua_service_secure_channel_1.MessageSecurityMode[this.securityMode] +
|
|
1131
1155
|
" policy = " +
|
|
1132
1156
|
this.securityPolicy);
|
|
1133
|
-
|
|
1157
|
+
callback(err1);
|
|
1158
|
+
return;
|
|
1134
1159
|
}
|
|
1135
1160
|
(0, node_opcua_assert_1.assert)(endpoint);
|
|
1136
1161
|
_verify_serverCertificate(this.clientCertificateManager, endpoint.serverCertificate)
|
|
1137
1162
|
.then(() => {
|
|
1138
1163
|
this.serverCertificate = endpoint.serverCertificate;
|
|
1139
|
-
callback(null, endpoint.endpointUrl);
|
|
1164
|
+
callback(null, endpoint.endpointUrl || "");
|
|
1140
1165
|
})
|
|
1141
1166
|
.catch((err1) => {
|
|
1142
1167
|
warningLog("[NODE-OPCUA-W25] client's server certificate verification has failed ", err1.message);
|
|
1143
1168
|
warningLog(" clientCertificateManager.rootDir = ", this.clientCertificateManager.rootDir);
|
|
1144
|
-
const f = (b) =>
|
|
1169
|
+
const f = (b) => ` ${b.toString("base64").replace(/(.{80})/g, "$1\n ")}`;
|
|
1145
1170
|
const chain = (0, web_1.split_der)(endpoint.serverCertificate);
|
|
1146
1171
|
warningLog(` server certificate contains ${chain.length} elements`);
|
|
1147
1172
|
for (let i = 0; i < chain.length; i++) {
|
|
1148
1173
|
const c = chain[i];
|
|
1149
|
-
warningLog("certificate", i,
|
|
1174
|
+
warningLog("certificate", i, `\n${f(c)}`);
|
|
1150
1175
|
}
|
|
1151
1176
|
if (chain.length > 1) {
|
|
1152
1177
|
warningLog(" verify also that the issuer certificate is trusted and the issuer's certificate is present in the issuer.cert folder\n" +
|
|
@@ -1155,7 +1180,7 @@ class ClientBaseImpl extends node_opcua_common_1.OPCUASecureObject {
|
|
|
1155
1180
|
else {
|
|
1156
1181
|
warningLog(" verify that the server certificate is trusted or that server certificate issuer's certificate is present in the issuer folder");
|
|
1157
1182
|
}
|
|
1158
|
-
|
|
1183
|
+
callback(err1);
|
|
1159
1184
|
});
|
|
1160
1185
|
});
|
|
1161
1186
|
}
|
|
@@ -1191,25 +1216,26 @@ class ClientBaseImpl extends node_opcua_common_1.OPCUASecureObject {
|
|
|
1191
1216
|
}
|
|
1192
1217
|
_close_pending_sessions(callback) {
|
|
1193
1218
|
const sessions = [...this._sessions];
|
|
1194
|
-
|
|
1195
|
-
(
|
|
1196
|
-
|
|
1197
|
-
|
|
1198
|
-
|
|
1199
|
-
|
|
1200
|
-
|
|
1201
|
-
|
|
1202
|
-
|
|
1203
|
-
|
|
1204
|
-
|
|
1205
|
-
|
|
1206
|
-
|
|
1207
|
-
|
|
1208
|
-
|
|
1209
|
-
}
|
|
1210
|
-
|
|
1211
|
-
|
|
1212
|
-
|
|
1219
|
+
const closeAll = async () => {
|
|
1220
|
+
for (const session of sessions) {
|
|
1221
|
+
(0, node_opcua_assert_1.assert)(session._client === this);
|
|
1222
|
+
await new Promise((resolve) => {
|
|
1223
|
+
let resolved = false;
|
|
1224
|
+
session.close((err) => {
|
|
1225
|
+
if (resolved)
|
|
1226
|
+
return;
|
|
1227
|
+
resolved = true;
|
|
1228
|
+
if (err) {
|
|
1229
|
+
const msg = session.authenticationToken ? session.authenticationToken.toString() : "";
|
|
1230
|
+
debugLog(` failing to close session ${msg}`);
|
|
1231
|
+
}
|
|
1232
|
+
resolve();
|
|
1233
|
+
});
|
|
1234
|
+
});
|
|
1235
|
+
}
|
|
1236
|
+
};
|
|
1237
|
+
closeAll()
|
|
1238
|
+
.then(() => {
|
|
1213
1239
|
// c8 ignore next
|
|
1214
1240
|
if (this._sessions.length > 0) {
|
|
1215
1241
|
debugLog(this._sessions
|
|
@@ -1217,8 +1243,9 @@ class ClientBaseImpl extends node_opcua_common_1.OPCUASecureObject {
|
|
|
1217
1243
|
.join(" "));
|
|
1218
1244
|
}
|
|
1219
1245
|
(0, node_opcua_assert_1.assert)(this._sessions.length === 0, " failed to disconnect exiting sessions ");
|
|
1220
|
-
callback(
|
|
1221
|
-
})
|
|
1246
|
+
callback();
|
|
1247
|
+
})
|
|
1248
|
+
.catch((err) => callback(err));
|
|
1222
1249
|
}
|
|
1223
1250
|
_install_secure_channel_event_handlers(secureChannel) {
|
|
1224
1251
|
(0, node_opcua_assert_1.assert)(this instanceof ClientBaseImpl);
|
|
@@ -1258,7 +1285,7 @@ class ClientBaseImpl extends node_opcua_common_1.OPCUASecureObject {
|
|
|
1258
1285
|
// secureChannel requests a new token
|
|
1259
1286
|
debugLog("SecureChannel Security Token ", token.tokenId, "live time was =", token.revisedLifetime, " is about to expired , it's time to request a new token");
|
|
1260
1287
|
// forward message to upper level
|
|
1261
|
-
this.emit("lifetime_75", token
|
|
1288
|
+
this.emit("lifetime_75", token);
|
|
1262
1289
|
});
|
|
1263
1290
|
secureChannel.on("security_token_renewed", (token) => {
|
|
1264
1291
|
// forward message to upper level
|
|
@@ -1275,7 +1302,7 @@ class ClientBaseImpl extends node_opcua_common_1.OPCUASecureObject {
|
|
|
1275
1302
|
/**
|
|
1276
1303
|
* @event connection_lost
|
|
1277
1304
|
*/
|
|
1278
|
-
this.emit("connection_lost"
|
|
1305
|
+
this.emit("connection_lost"); // instead of "close"
|
|
1279
1306
|
}
|
|
1280
1307
|
// this is a normal close operation initiated by us
|
|
1281
1308
|
this.emit("close", err); // instead of "close"
|
|
@@ -1289,7 +1316,7 @@ class ClientBaseImpl extends node_opcua_common_1.OPCUASecureObject {
|
|
|
1289
1316
|
/**
|
|
1290
1317
|
* @event connection_lost
|
|
1291
1318
|
*/
|
|
1292
|
-
this.emit("connection_lost"
|
|
1319
|
+
this.emit("connection_lost"); // instead of "close"
|
|
1293
1320
|
this._repairConnection();
|
|
1294
1321
|
}
|
|
1295
1322
|
}
|
|
@@ -1408,10 +1435,10 @@ class ClientBaseImpl extends node_opcua_common_1.OPCUASecureObject {
|
|
|
1408
1435
|
* @internal
|
|
1409
1436
|
* @private
|
|
1410
1437
|
*/
|
|
1411
|
-
__createSession_step2(
|
|
1438
|
+
__createSession_step2(_session, _callback) {
|
|
1412
1439
|
throw new Error("Please override");
|
|
1413
1440
|
}
|
|
1414
|
-
_activateSession(
|
|
1441
|
+
_activateSession(_session, _userIdentity, _callback) {
|
|
1415
1442
|
throw new Error("Please override");
|
|
1416
1443
|
}
|
|
1417
1444
|
}
|
|
@@ -1419,22 +1446,23 @@ exports.ClientBaseImpl = ClientBaseImpl;
|
|
|
1419
1446
|
// tslint:disable-next-line: max-classes-per-file
|
|
1420
1447
|
class TmpClient extends ClientBaseImpl {
|
|
1421
1448
|
constructor(options) {
|
|
1422
|
-
options.clientName =
|
|
1449
|
+
options.clientName = `${options.clientName || ""}_TmpClient`;
|
|
1423
1450
|
super(options);
|
|
1424
1451
|
}
|
|
1425
1452
|
connect(endpoint, callback) {
|
|
1426
1453
|
debugLog("connecting to TmpClient");
|
|
1427
1454
|
// c8 ignore next
|
|
1428
1455
|
if (this._internalState !== "disconnected") {
|
|
1429
|
-
callback(new Error(
|
|
1456
|
+
callback?.(new Error(`TmpClient#connect: invalid internal state = ${this._internalState}`));
|
|
1430
1457
|
return;
|
|
1431
1458
|
}
|
|
1432
1459
|
this._setInternalState("connecting");
|
|
1433
1460
|
this._connectStep2(endpoint, (err) => {
|
|
1434
1461
|
if (this.isUnusable()) {
|
|
1435
|
-
|
|
1462
|
+
this._handleUnrecoverableConnectionFailure(new Error("premature disconnection 4"), callback || (() => { }));
|
|
1463
|
+
return;
|
|
1436
1464
|
}
|
|
1437
|
-
callback(err);
|
|
1465
|
+
callback?.(err);
|
|
1438
1466
|
});
|
|
1439
1467
|
}
|
|
1440
1468
|
}
|