node-opcua-client 2.73.1 → 2.76.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.
Files changed (83) hide show
  1. package/LICENSE +3 -1
  2. package/README.md +54 -0
  3. package/dist/alarms_and_conditions/client_alarm.d.ts +49 -45
  4. package/dist/alarms_and_conditions/client_alarm.js +109 -101
  5. package/dist/alarms_and_conditions/client_alarm.js.map +1 -1
  6. package/dist/alarms_and_conditions/client_alarm_list.d.ts +25 -25
  7. package/dist/alarms_and_conditions/client_alarm_list.js +97 -97
  8. package/dist/alarms_and_conditions/client_alarm_list.js.map +1 -1
  9. package/dist/alarms_and_conditions/client_alarm_tools.d.ts +4 -4
  10. package/dist/alarms_and_conditions/client_alarm_tools.js +156 -152
  11. package/dist/alarms_and_conditions/client_alarm_tools.js.map +1 -1
  12. package/dist/alarms_and_conditions/client_alarm_tools_acknowledge_all_conditions.d.ts +18 -18
  13. package/dist/alarms_and_conditions/client_alarm_tools_acknowledge_all_conditions.js +192 -190
  14. package/dist/alarms_and_conditions/client_alarm_tools_acknowledge_all_conditions.js.map +1 -1
  15. package/dist/alarms_and_conditions/client_alarm_tools_dump_event.d.ts +9 -9
  16. package/dist/alarms_and_conditions/client_alarm_tools_dump_event.js +73 -73
  17. package/dist/alarms_and_conditions/client_alarm_tools_extractConditionFields.d.ts +3 -8
  18. package/dist/alarms_and_conditions/client_alarm_tools_extractConditionFields.js +118 -120
  19. package/dist/alarms_and_conditions/client_alarm_tools_extractConditionFields.js.map +1 -1
  20. package/dist/alarms_and_conditions/client_tools.d.ts +7 -7
  21. package/dist/alarms_and_conditions/client_tools.js +180 -180
  22. package/dist/client_base.d.ts +277 -277
  23. package/dist/client_base.js +14 -14
  24. package/dist/client_monitored_item.d.ts +21 -21
  25. package/dist/client_monitored_item.js +11 -11
  26. package/dist/client_monitored_item_base.d.ts +39 -39
  27. package/dist/client_monitored_item_base.js +2 -2
  28. package/dist/client_monitored_item_group.d.ts +18 -18
  29. package/dist/client_monitored_item_group.js +13 -13
  30. package/dist/client_monitored_item_toolbox.d.ts +15 -15
  31. package/dist/client_monitored_item_toolbox.js +117 -117
  32. package/dist/client_session.d.ts +484 -484
  33. package/dist/client_session.js +10 -10
  34. package/dist/client_session_keepalive_manager.d.ts +34 -34
  35. package/dist/client_session_keepalive_manager.js +150 -150
  36. package/dist/client_subscription.d.ts +241 -241
  37. package/dist/client_subscription.js +14 -14
  38. package/dist/client_utils.d.ts +22 -22
  39. package/dist/client_utils.js +88 -88
  40. package/dist/common.d.ts +17 -17
  41. package/dist/common.js +5 -5
  42. package/dist/index.d.ts +55 -55
  43. package/dist/index.js +93 -93
  44. package/dist/opcua_client.d.ts +132 -132
  45. package/dist/opcua_client.js +33 -33
  46. package/dist/private/client_base_impl.d.ts +157 -157
  47. package/dist/private/client_base_impl.js +1337 -1337
  48. package/dist/private/client_monitored_item_base_impl.d.ts +3 -3
  49. package/dist/private/client_monitored_item_base_impl.js +4 -4
  50. package/dist/private/client_monitored_item_group_impl.d.ts +53 -53
  51. package/dist/private/client_monitored_item_group_impl.js +159 -159
  52. package/dist/private/client_monitored_item_impl.d.ts +93 -93
  53. package/dist/private/client_monitored_item_impl.js +305 -304
  54. package/dist/private/client_monitored_item_impl.js.map +1 -1
  55. package/dist/private/client_publish_engine.d.ts +62 -62
  56. package/dist/private/client_publish_engine.js +408 -408
  57. package/dist/private/client_session_impl.d.ts +621 -621
  58. package/dist/private/client_session_impl.js +1302 -1301
  59. package/dist/private/client_session_impl.js.map +1 -1
  60. package/dist/private/client_subscription_impl.d.ts +93 -93
  61. package/dist/private/client_subscription_impl.js +748 -743
  62. package/dist/private/client_subscription_impl.js.map +1 -1
  63. package/dist/private/i_private_client.d.ts +18 -18
  64. package/dist/private/i_private_client.js +2 -2
  65. package/dist/private/opcua_client_impl.d.ts +169 -169
  66. package/dist/private/opcua_client_impl.js +981 -981
  67. package/dist/reconnection.d.ts +9 -9
  68. package/dist/reconnection.js +408 -408
  69. package/dist/tools/findservers.d.ts +20 -20
  70. package/dist/tools/findservers.js +61 -61
  71. package/dist/tools/read_history_server_capabilities.d.ts +6 -6
  72. package/dist/tools/read_history_server_capabilities.js +99 -99
  73. package/dist/verify.d.ts +5 -5
  74. package/dist/verify.js +134 -134
  75. package/package.json +48 -48
  76. package/source/alarms_and_conditions/client_alarm.ts +28 -17
  77. package/source/alarms_and_conditions/client_alarm_list.ts +1 -0
  78. package/source/alarms_and_conditions/client_alarm_tools.ts +33 -23
  79. package/source/alarms_and_conditions/client_alarm_tools_acknowledge_all_conditions.ts +10 -4
  80. package/source/alarms_and_conditions/client_alarm_tools_extractConditionFields.ts +11 -11
  81. package/source/private/client_monitored_item_impl.ts +4 -3
  82. package/source/private/client_session_impl.ts +10 -2
  83. package/source/private/client_subscription_impl.ts +6 -2
@@ -1,982 +1,982 @@
1
- "use strict";
2
- /**
3
- * @module node-opcua-client-private
4
- */
5
- // tslint:disable:variable-name
6
- // tslint:disable:no-console
7
- // tslint:disable:no-empty
8
- var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
9
- function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
10
- return new (P || (P = Promise))(function (resolve, reject) {
11
- function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
12
- function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
13
- function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
14
- step((generator = generator.apply(thisArg, _arguments || [])).next());
15
- });
16
- };
17
- Object.defineProperty(exports, "__esModule", { value: true });
18
- exports.OPCUAClientImpl = void 0;
19
- const crypto = require("crypto");
20
- const util_1 = require("util");
21
- const async = require("async");
22
- const chalk = require("chalk");
23
- const node_opcua_assert_1 = require("node-opcua-assert");
24
- const node_opcua_buffer_utils_1 = require("node-opcua-buffer-utils");
25
- const node_opcua_crypto_1 = require("node-opcua-crypto");
26
- const node_opcua_data_model_1 = require("node-opcua-data-model");
27
- const node_opcua_debug_1 = require("node-opcua-debug");
28
- const node_opcua_hostname_1 = require("node-opcua-hostname");
29
- const node_opcua_secure_channel_1 = require("node-opcua-secure-channel");
30
- const node_opcua_service_endpoints_1 = require("node-opcua-service-endpoints");
31
- const node_opcua_service_secure_channel_1 = require("node-opcua-service-secure-channel");
32
- const node_opcua_service_session_1 = require("node-opcua-service-session");
33
- const node_opcua_status_code_1 = require("node-opcua-status-code");
34
- const node_opcua_utils_1 = require("node-opcua-utils");
35
- const opcua_client_1 = require("../opcua_client");
36
- const reconnection_1 = require("../reconnection");
37
- const client_base_impl_1 = require("./client_base_impl");
38
- const client_session_impl_1 = require("./client_session_impl");
39
- const client_subscription_impl_1 = require("./client_subscription_impl");
40
- const doDebug = (0, node_opcua_debug_1.checkDebugFlag)(__filename);
41
- const debugLog = (0, node_opcua_debug_1.make_debugLog)(__filename);
42
- const errorLog = (0, node_opcua_debug_1.make_errorLog)(__filename);
43
- const warningLog = (0, node_opcua_debug_1.make_warningLog)(__filename);
44
- function validateServerNonce(serverNonce) {
45
- return !(serverNonce && serverNonce.length < 32) || (serverNonce && serverNonce.length === 0);
46
- }
47
- function verifyEndpointDescriptionMatches(client, responseServerEndpoints) {
48
- // The Server returns its EndpointDescriptions in the response. Clients use this information to
49
- // determine whether the list of EndpointDescriptions returned from the Discovery Endpoint matches
50
- // the Endpoints that the Server has. If there is a difference then the Client shall close the
51
- // Session and report an error.
52
- // The Server returns all EndpointDescriptions for the serverUri
53
- // specified by the Client in the request. The Client only verifies EndpointDescriptions with a
54
- // transportProfileUri that matches the profileUri specified in the original GetEndpoints request.
55
- // A Client may skip this check if the EndpointDescriptions were provided by a trusted source
56
- // such as the Administrator.
57
- // serverEndpoints:
58
- // The Client shall verify this list with the list from a Discovery Endpoint if it used a Discovery Endpoint
59
- // fetch to the EndpointDescriptions.
60
- // ToDo
61
- return true;
62
- }
63
- function findUserTokenPolicy(endpointDescription, userTokenType) {
64
- endpointDescription.userIdentityTokens = endpointDescription.userIdentityTokens || [];
65
- const r = endpointDescription.userIdentityTokens.filter((userIdentity) => userIdentity.tokenType === userTokenType);
66
- return r.length === 0 ? null : r[0];
67
- }
68
- function createAnonymousIdentityToken(context) {
69
- const endpoint = context.endpoint;
70
- const userTokenPolicy = findUserTokenPolicy(endpoint, node_opcua_service_endpoints_1.UserTokenType.Anonymous);
71
- if (!userTokenPolicy) {
72
- throw new Error("Cannot find ANONYMOUS user token policy in end point description");
73
- }
74
- return new node_opcua_service_session_1.AnonymousIdentityToken({ policyId: userTokenPolicy.policyId });
75
- }
76
- /**
77
- *
78
- * @param context
79
- * @param certificate - the user certificate
80
- * @param privateKey - the private key associated with the user certificate
81
- */
82
- function createX509IdentityToken(context, certificate, privateKey) {
83
- const endpoint = context.endpoint;
84
- (0, node_opcua_assert_1.assert)(endpoint instanceof node_opcua_service_endpoints_1.EndpointDescription);
85
- const userTokenPolicy = findUserTokenPolicy(endpoint, node_opcua_service_endpoints_1.UserTokenType.Certificate);
86
- // istanbul ignore next
87
- if (!userTokenPolicy) {
88
- throw new Error("Cannot find Certificate (X509) user token policy in end point description");
89
- }
90
- let securityPolicy = (0, node_opcua_secure_channel_1.fromURI)(userTokenPolicy.securityPolicyUri);
91
- // if the security policy is not specified we use the session security policy
92
- if (securityPolicy === node_opcua_secure_channel_1.SecurityPolicy.Invalid) {
93
- securityPolicy = context.securityPolicy;
94
- }
95
- const userIdentityToken = new node_opcua_service_session_1.X509IdentityToken({
96
- certificateData: certificate,
97
- policyId: userTokenPolicy.policyId
98
- });
99
- const serverCertificate = context.serverCertificate;
100
- (0, node_opcua_assert_1.assert)(serverCertificate instanceof Buffer);
101
- const serverNonce = context.serverNonce || Buffer.alloc(0);
102
- (0, node_opcua_assert_1.assert)(serverNonce instanceof Buffer);
103
- // see Release 1.02 155 OPC Unified Architecture, Part 4
104
- const cryptoFactory = (0, node_opcua_secure_channel_1.getCryptoFactory)(securityPolicy);
105
- // istanbul ignore next
106
- if (!cryptoFactory) {
107
- throw new Error(" Unsupported security Policy");
108
- }
109
- /**
110
- * OPCUA Spec 1.04 - part 4
111
- * page 28:
112
- * 5.6.3.1
113
- * ...
114
- * If the token is an X509IdentityToken then the proof is a signature generated with private key
115
- * associated with the Certificate. The data to sign is created by appending the last serverNonce to
116
- * the **serverCertificate** specified in the CreateSession response. If a token includes a secret then it
117
- * should be encrypted using the public key from the serverCertificate.
118
- *
119
- * page 155:
120
- * Token Encryption and Proof of Possession
121
- * 7.36.2.1 Overview
122
- * The Client shall always prove possession of a UserIdentityToken when it passes it to the Server.
123
- * Some tokens include a secret such as a password which the Server will accept as proof. In order
124
- * to protect these secrets the Token may be encrypted before it is passed to the Server. Other types
125
- * of tokens allow the Client to create a signature with the secret associated with the Token. In these
126
- * cases, the Client proves possession of a UserIdentityToken by creating a signature with the secret
127
- * and passing it to the Server
128
- *
129
- * page 159:
130
- * 7.36.5 X509IdentityTokens
131
- * The X509IdentityToken is used to pass an X.509 v3 Certificate which is issued by the user.
132
- * This token shall always be accompanied by a Signature in the userTokenSignature parameter of
133
- * ActivateSession if required by the SecurityPolicy. The Server should specify a SecurityPolicy for
134
- * the UserTokenPolicy if the SecureChannel has a SecurityPolicy of None.
135
- */
136
- // now create the proof of possession, by creating a signature
137
- // The data to sign is created by appending the last serverNonce to the serverCertificate
138
- // The signature generated with private key associated with the User Certificate
139
- const userTokenSignature = (0, node_opcua_secure_channel_1.computeSignature)(serverCertificate, serverNonce, privateKey, securityPolicy);
140
- return { userIdentityToken, userTokenSignature };
141
- }
142
- function createUserNameIdentityToken(session, userName, password) {
143
- // assert(endpoint instanceof EndpointDescription);
144
- (0, node_opcua_assert_1.assert)(userName === null || typeof userName === "string");
145
- (0, node_opcua_assert_1.assert)(password === null || typeof password === "string");
146
- const endpoint = session.endpoint;
147
- (0, node_opcua_assert_1.assert)(endpoint instanceof node_opcua_service_endpoints_1.EndpointDescription);
148
- /**
149
- * OPC Unified Architecture 1.0.4: Part 4 155
150
- * Each UserIdentityToken allowed by an Endpoint shall have a UserTokenPolicy specified in the
151
- * EndpointDescription. The UserTokenPolicy specifies what SecurityPolicy to use when encrypting
152
- * or signing. If this SecurityPolicy is omitted then the Client uses the SecurityPolicy in the
153
- * EndpointDescription. If the matching SecurityPolicy is set to None then no encryption or signature
154
- * is required.
155
- *
156
- */
157
- const userTokenPolicy = findUserTokenPolicy(endpoint, node_opcua_service_endpoints_1.UserTokenType.UserName);
158
- // istanbul ignore next
159
- if (!userTokenPolicy) {
160
- throw new Error("Cannot find USERNAME user token policy in end point description");
161
- }
162
- let securityPolicy = (0, node_opcua_secure_channel_1.fromURI)(userTokenPolicy.securityPolicyUri);
163
- // if the security policy is not specified we use the session security policy
164
- if (securityPolicy === node_opcua_secure_channel_1.SecurityPolicy.Invalid) {
165
- securityPolicy = session.securityPolicy;
166
- }
167
- let identityToken;
168
- let serverCertificate = session.serverCertificate;
169
- // if server does not provide certificate use unencrypted password
170
- if (!serverCertificate) {
171
- identityToken = new node_opcua_service_session_1.UserNameIdentityToken({
172
- encryptionAlgorithm: null,
173
- password: Buffer.from(password, "utf-8"),
174
- policyId: userTokenPolicy ? userTokenPolicy.policyId : null,
175
- userName
176
- });
177
- return identityToken;
178
- }
179
- (0, node_opcua_assert_1.assert)(serverCertificate instanceof Buffer);
180
- serverCertificate = (0, node_opcua_crypto_1.toPem)(serverCertificate, "CERTIFICATE");
181
- const publicKey = (0, node_opcua_crypto_1.extractPublicKeyFromCertificateSync)(serverCertificate);
182
- const serverNonce = session.serverNonce || Buffer.alloc(0);
183
- (0, node_opcua_assert_1.assert)(serverNonce instanceof Buffer);
184
- // If None is specified for the UserTokenPolicy and SecurityPolicy is None
185
- // then the password only contains the UTF-8 encoded password.
186
- // note: this means that password is sent in clear text to the server
187
- // note: OPCUA specification discourages use of unencrypted password
188
- // but some old OPCUA server may only provide this policy and we
189
- // still have to support in the client?
190
- if (securityPolicy === node_opcua_secure_channel_1.SecurityPolicy.None) {
191
- identityToken = new node_opcua_service_session_1.UserNameIdentityToken({
192
- encryptionAlgorithm: null,
193
- password: Buffer.from(password, "utf-8"),
194
- policyId: userTokenPolicy.policyId,
195
- userName
196
- });
197
- return identityToken;
198
- }
199
- // see Release 1.02 155 OPC Unified Architecture, Part 4
200
- const cryptoFactory = (0, node_opcua_secure_channel_1.getCryptoFactory)(securityPolicy);
201
- // istanbul ignore next
202
- if (!cryptoFactory) {
203
- throw new Error(" Unsupported security Policy " + securityPolicy.toString());
204
- }
205
- identityToken = new node_opcua_service_session_1.UserNameIdentityToken({
206
- encryptionAlgorithm: cryptoFactory.asymmetricEncryptionAlgorithm,
207
- password: Buffer.from(password, "utf-8"),
208
- policyId: userTokenPolicy.policyId,
209
- userName
210
- });
211
- // now encrypt password as requested
212
- const lenBuf = (0, node_opcua_buffer_utils_1.createFastUninitializedBuffer)(4);
213
- lenBuf.writeUInt32LE(identityToken.password.length + serverNonce.length, 0);
214
- const block = Buffer.concat([lenBuf, identityToken.password, serverNonce]);
215
- identityToken.password = cryptoFactory.asymmetricEncrypt(block, publicKey);
216
- return identityToken;
217
- }
218
- function _adjustRevisedSessionTimeout(revisedSessionTimeout, requestedTimeout) {
219
- // Some old OPCUA Servers are known to report an invalid revisedSessionTimeout
220
- // such as Siemens SimoCode Pro V.
221
- // we need to adjust the value here, by guessing a sensible sessionTimeout value to use instead.
222
- if (revisedSessionTimeout < 1e-10) {
223
- warningLog(`the revisedSessionTimeout ${revisedSessionTimeout} reported by the server is inconsistent and has been adjusted back to requestedTimeout ${requestedTimeout}`);
224
- return requestedTimeout;
225
- }
226
- if (revisedSessionTimeout < OPCUAClientImpl.minimumRevisedSessionTimeout) {
227
- warningLog(`the revisedSessionTimeout ${revisedSessionTimeout} is smaller than the minimum timeout (OPCUAClientImpl.minimumRevisedSessionTimeout = ${OPCUAClientImpl.minimumRevisedSessionTimeout}) and has been clamped to this value`);
228
- return OPCUAClientImpl.minimumRevisedSessionTimeout;
229
- }
230
- return revisedSessionTimeout;
231
- }
232
- /***
233
- * @constructor
234
- * @internal
235
- */
236
- class OPCUAClientImpl extends client_base_impl_1.ClientBaseImpl {
237
- constructor(options) {
238
- options = options || {};
239
- super(options);
240
- // @property endpointMustExist {Boolean}
241
- // if set to true , create Session will only accept connection from server which endpoint_url has been reported
242
- // by GetEndpointsRequest.
243
- // By default, the client is strict.
244
- if (Object.prototype.hasOwnProperty.call(options, "endpoint_must_exist")) {
245
- if (Object.prototype.hasOwnProperty.call(options, "endpointMustExist")) {
246
- throw new Error("endpoint_must_exist is deprecated! you must now use endpointMustExist instead of endpoint_must_exist ");
247
- }
248
- warningLog("Warning: endpoint_must_exist is now deprecated, use endpointMustExist instead");
249
- options.endpointMustExist = options.endpoint_must_exist;
250
- }
251
- this.endpointMustExist = (0, node_opcua_utils_1.isNullOrUndefined)(options.endpointMustExist) ? true : !!options.endpointMustExist;
252
- this.requestedSessionTimeout = options.requestedSessionTimeout || 60000; // 1 minute
253
- this.___sessionName_counter = 0;
254
- this.userIdentityInfo = { type: node_opcua_service_endpoints_1.UserTokenType.Anonymous };
255
- this.endpoint = undefined;
256
- }
257
- static create(options) {
258
- return new OPCUAClientImpl(options);
259
- }
260
- /**
261
- * @internal
262
- * @param args
263
- *
264
- */
265
- createSession(...args) {
266
- if (args.length === 1) {
267
- return this.createSession({ type: node_opcua_service_endpoints_1.UserTokenType.Anonymous }, args[0]);
268
- }
269
- const userIdentityInfo = args[0] || { type: node_opcua_service_endpoints_1.UserTokenType.Anonymous };
270
- const callback = args[1];
271
- this.userIdentityInfo = userIdentityInfo;
272
- (0, node_opcua_assert_1.assert)(typeof callback === "function");
273
- this._createSession((err, session) => {
274
- if (err) {
275
- callback(err);
276
- }
277
- else {
278
- /* istanbul ignore next */
279
- if (!session) {
280
- return callback(new Error("Internal Error"));
281
- }
282
- this._addSession(session);
283
- this._activateSession(session, (err1, session2) => {
284
- callback(err1, session2);
285
- });
286
- }
287
- });
288
- }
289
- createSession2(...args) {
290
- if (args.length === 1) {
291
- return this.createSession2({ type: node_opcua_service_endpoints_1.UserTokenType.Anonymous }, args[0]);
292
- }
293
- const userIdentityInfo = args[0];
294
- const callback = args[1];
295
- if (!this._secureChannel) {
296
- // we do not have a connection anymore
297
- return callback(new Error("Connection is closed"));
298
- }
299
- return this.createSession(args[0], (err, session) => {
300
- if (err && err.message.match(/BadTooManySessions/)) {
301
- const delayToRetry = 5; // seconds
302
- errorLog(`TooManySession .... we need to retry later ... in ${delayToRetry} secondes`);
303
- const retryCreateSessionTimer = setTimeout(() => {
304
- errorLog("TooManySession .... now retrying");
305
- this.createSession2(userIdentityInfo, callback);
306
- }, delayToRetry * 1000);
307
- return;
308
- }
309
- callback(err, session);
310
- });
311
- }
312
- /**
313
- * @internal
314
- * @param args
315
- */
316
- changeSessionIdentity(...args) {
317
- const session = args[0];
318
- const userIdentityInfo = args[1];
319
- const callback = args[2];
320
- (0, node_opcua_assert_1.assert)(typeof callback === "function");
321
- const old_userIdentity = this.userIdentityInfo;
322
- this.userIdentityInfo = userIdentityInfo;
323
- this._activateSession(session, (err1, session1) => {
324
- callback(err1 ? err1 : undefined);
325
- });
326
- }
327
- /**
328
- * @internals
329
- * @param args
330
- */
331
- closeSession(...args) {
332
- super.closeSession(...args);
333
- }
334
- toString() {
335
- let str = client_base_impl_1.ClientBaseImpl.prototype.toString.call(this);
336
- str += " requestedSessionTimeout....... " + this.requestedSessionTimeout + "\n";
337
- str += " endpointUrl................... " + this.endpointUrl + "\n";
338
- str += " serverUri..................... " + this.serverUri + "\n";
339
- return str;
340
- }
341
- /**
342
- *
343
- * @example
344
- *
345
- * ```javascript
346
- *
347
- * const session = await OPCUAClient.createSession(endpointUrl);
348
- * const dataValue = await session.read({ nodeId, attributeId: AttributeIds.Value });
349
- * await session.close();
350
- *
351
- * ```
352
- * @stability experimental
353
- *
354
- * @param endpointUrl
355
- * @param userIdentity
356
- * @returns session
357
- *
358
- *
359
- * const create
360
- */
361
- static createSession(endpointUrl, userIdentity, clientOptions) {
362
- return __awaiter(this, void 0, void 0, function* () {
363
- const client = opcua_client_1.OPCUAClient.create(clientOptions || {});
364
- yield client.connect(endpointUrl);
365
- const session = yield client.createSession2(userIdentity);
366
- const oldClose = session.close;
367
- session.close = thenify.withCallback((...args) => {
368
- if (args.length === 1) {
369
- return session.close(true, args[0]);
370
- }
371
- const deleteSubscriptions = args[0];
372
- const callback = args[1];
373
- session.close = oldClose;
374
- oldClose.call(session, deleteSubscriptions, (err) => {
375
- client.disconnect((err) => {
376
- callback(err);
377
- });
378
- });
379
- });
380
- return session;
381
- });
382
- }
383
- /**
384
- * @internal
385
- * @param args
386
- */
387
- withSession(connectionPoint, inner_func, ...args) {
388
- const endpointUrl = typeof connectionPoint === "string" ? connectionPoint : connectionPoint.endpointUrl;
389
- const userIdentity = typeof connectionPoint === "string" ? { type: node_opcua_service_endpoints_1.UserTokenType.Anonymous } : connectionPoint.userIdentity;
390
- const callback = args[0];
391
- (0, node_opcua_assert_1.assert)(typeof inner_func === "function", "expecting inner function");
392
- (0, node_opcua_assert_1.assert)(typeof callback === "function", "expecting callback function");
393
- let theSession;
394
- let the_error;
395
- let need_disconnect = false;
396
- async.series([
397
- // step 1 : connect to
398
- (innerCallback) => {
399
- this.connect(endpointUrl, (err) => {
400
- need_disconnect = true;
401
- if (err) {
402
- warningLog(err.message);
403
- errorLog(" cannot connect to endpoint :", endpointUrl);
404
- }
405
- innerCallback(err);
406
- });
407
- },
408
- // step 2 : createSession
409
- (innerCallback) => {
410
- this.createSession2(userIdentity, (err, session) => {
411
- if (err) {
412
- return innerCallback(err);
413
- }
414
- if (!session) {
415
- return innerCallback(new Error("internal error"));
416
- }
417
- theSession = session;
418
- innerCallback();
419
- });
420
- },
421
- (innerCallback) => {
422
- try {
423
- inner_func(theSession, (err) => {
424
- the_error = err;
425
- innerCallback();
426
- });
427
- }
428
- catch (err) {
429
- console.log("Exception catch in inner function, check your code ", err);
430
- errorLog("OPCUAClientImpl#withClientSession", err.message);
431
- the_error = err;
432
- innerCallback();
433
- }
434
- },
435
- // close session
436
- (innerCallback) => {
437
- theSession.close(/*deleteSubscriptions=*/ true, (err) => {
438
- if (err) {
439
- debugLog("OPCUAClientImpl#withClientSession: session closed failed ?");
440
- }
441
- innerCallback();
442
- });
443
- },
444
- (innerCallback) => {
445
- this.disconnect((err) => {
446
- need_disconnect = false;
447
- if (err) {
448
- errorLog("OPCUAClientImpl#withClientSession: client disconnect failed ?");
449
- }
450
- innerCallback();
451
- });
452
- }
453
- ], (err1) => {
454
- if (err1) {
455
- console.log("err", err1.message);
456
- }
457
- if (need_disconnect) {
458
- errorLog("Disconnecting client after failure");
459
- this.disconnect((err2) => {
460
- return callback(the_error || err1 || err2);
461
- });
462
- }
463
- else {
464
- return callback(the_error || err1);
465
- }
466
- });
467
- }
468
- withSubscription(endpointUrl, subscriptionParameters, innerFunc, callback) {
469
- (0, node_opcua_assert_1.assert)(typeof innerFunc === "function");
470
- (0, node_opcua_assert_1.assert)(typeof callback === "function");
471
- this.withSession(endpointUrl, (session, done) => {
472
- (0, node_opcua_assert_1.assert)(typeof done === "function");
473
- const subscription = new client_subscription_impl_1.ClientSubscriptionImpl(session, subscriptionParameters);
474
- try {
475
- innerFunc(session, subscription, (err) => {
476
- subscription.terminate((err1) => {
477
- done(err1);
478
- });
479
- });
480
- }
481
- catch (err) {
482
- debugLog(err);
483
- done(err);
484
- }
485
- }, callback);
486
- }
487
- withSessionAsync(connectionPoint, func) {
488
- return __awaiter(this, void 0, void 0, function* () {
489
- (0, node_opcua_assert_1.assert)(typeof func === "function");
490
- (0, node_opcua_assert_1.assert)(func.length === 1, "expecting a single argument in func");
491
- const endpointUrl = typeof connectionPoint === "string" ? connectionPoint : connectionPoint.endpointUrl;
492
- const userIdentity = typeof connectionPoint === "string" ? { type: node_opcua_service_endpoints_1.UserTokenType.Anonymous } : connectionPoint.userIdentity;
493
- yield this.connect(endpointUrl);
494
- const session = yield this.createSession2(userIdentity);
495
- let result;
496
- try {
497
- result = yield func(session);
498
- }
499
- catch (err) {
500
- errorLog(err);
501
- throw err;
502
- }
503
- finally {
504
- yield session.close();
505
- yield this.disconnect();
506
- }
507
- return result;
508
- });
509
- }
510
- withSubscriptionAsync(connectionPoint, parameters, func) {
511
- return __awaiter(this, void 0, void 0, function* () {
512
- yield this.withSessionAsync(connectionPoint, (session) => __awaiter(this, void 0, void 0, function* () {
513
- (0, node_opcua_assert_1.assert)(session, " session must exist");
514
- const subscription = yield session.createSubscription2(parameters);
515
- try {
516
- const result = yield func(session, subscription);
517
- return result;
518
- }
519
- catch (err) {
520
- console.log("withSubscriptionAsync inner function failed ", err.message);
521
- throw err;
522
- }
523
- finally {
524
- yield subscription.terminate();
525
- }
526
- }));
527
- });
528
- }
529
- reactivateSession(session, callback) {
530
- const internalSession = session;
531
- (0, node_opcua_assert_1.assert)(typeof callback === "function");
532
- if (!this._secureChannel) {
533
- return callback(new Error(" client must be connected first"));
534
- }
535
- // istanbul ignore next
536
- if (!this.__resolveEndPoint() || !this.endpoint) {
537
- return callback(new Error(" End point must exist " + this._secureChannel.endpointUrl));
538
- }
539
- (0, node_opcua_assert_1.assert)(!internalSession._client || (0, node_opcua_utils_1.matchUri)(internalSession._client.endpointUrl, this.endpointUrl), "cannot reactivateSession on a different endpoint");
540
- const old_client = internalSession._client;
541
- debugLog("OPCUAClientImpl#reactivateSession");
542
- this._activateSession(internalSession, (err /*, newSession?: ClientSessionImpl*/) => {
543
- if (!err) {
544
- if (old_client !== this) {
545
- // remove session from old client:
546
- if (old_client) {
547
- old_client._removeSession(internalSession);
548
- (0, node_opcua_assert_1.assert)(old_client._sessions.indexOf(internalSession) === -1);
549
- }
550
- this._addSession(internalSession);
551
- (0, node_opcua_assert_1.assert)(internalSession._client === this);
552
- (0, node_opcua_assert_1.assert)(!internalSession._closed, "session should not vbe closed");
553
- (0, node_opcua_assert_1.assert)(this._sessions.indexOf(internalSession) !== -1);
554
- }
555
- callback();
556
- }
557
- else {
558
- // istanbul ignore next
559
- if (doDebug) {
560
- debugLog(chalk.red.bgWhite("reactivateSession has failed !"), err.message);
561
- }
562
- callback(err);
563
- }
564
- });
565
- }
566
- /**
567
- * @internal
568
- * @private
569
- */
570
- _on_connection_reestablished(callback) {
571
- (0, node_opcua_assert_1.assert)(typeof callback === "function");
572
- // call base class implementation first
573
- client_base_impl_1.ClientBaseImpl.prototype._on_connection_reestablished.call(this, ( /*err?: Error*/) => {
574
- (0, reconnection_1.repair_client_sessions)(this, callback);
575
- });
576
- }
577
- /**
578
- *
579
- * @internal
580
- * @private
581
- */
582
- __createSession_step3(session, callback) {
583
- (0, node_opcua_assert_1.assert)(typeof callback === "function");
584
- (0, node_opcua_assert_1.assert)(this.serverUri !== undefined, " must have a valid server URI " + this.serverUri);
585
- (0, node_opcua_assert_1.assert)(this.endpointUrl !== undefined, " must have a valid server endpointUrl");
586
- (0, node_opcua_assert_1.assert)(this.endpoint);
587
- // istanbul ignore next
588
- if (!this._secureChannel) {
589
- return callback(new Error("Invalid channel"));
590
- }
591
- const applicationUri = this._getApplicationUri();
592
- const applicationDescription = {
593
- applicationName: new node_opcua_data_model_1.LocalizedText({ text: this.applicationName, locale: null }),
594
- applicationType: node_opcua_service_endpoints_1.ApplicationType.Client,
595
- applicationUri,
596
- discoveryProfileUri: undefined,
597
- discoveryUrls: [],
598
- gatewayServerUri: undefined,
599
- productUri: "NodeOPCUA-Client"
600
- };
601
- // note : do not confuse CreateSessionRequest.clientNonce with OpenSecureChannelRequest.clientNonce
602
- // which are two different nonce, with different size (although they share the same name )
603
- this.clientNonce = crypto.randomBytes(32);
604
- const request = new node_opcua_service_session_1.CreateSessionRequest({
605
- clientCertificate: this.getCertificate(),
606
- clientDescription: applicationDescription,
607
- clientNonce: this.clientNonce,
608
- endpointUrl: this.endpointUrl,
609
- maxResponseMessageSize: 800000,
610
- requestedSessionTimeout: this.requestedSessionTimeout,
611
- serverUri: this.serverUri,
612
- sessionName: this._nextSessionName()
613
- });
614
- // a client Nonce must be provided if security mode is set
615
- (0, node_opcua_assert_1.assert)(this._secureChannel.securityMode === node_opcua_service_secure_channel_1.MessageSecurityMode.None || request.clientNonce !== null);
616
- this.performMessageTransaction(request, (err, response) => {
617
- /* istanbul ignore next */
618
- if (err) {
619
- console.log("__createSession_step3 has failed", err.message);
620
- return callback(err);
621
- // //xxxxxx qdqsdqsdqsdqsd
622
- // // we could have an invalid state here or a connection error
623
- // errorLog("error: ", err.message, " retrying in ... 5 secondes");
624
- // setTimeout(() => {
625
- // errorLog(" .... now retrying");
626
- // this.__createSession_step3(session, callback);
627
- // }, 5 * 1000);
628
- // return;
629
- }
630
- /* istanbul ignore next */
631
- if (!response || !(response instanceof node_opcua_service_session_1.CreateSessionResponse)) {
632
- return callback(new Error("internal error"));
633
- }
634
- if (response.responseHeader.serviceResult === node_opcua_status_code_1.StatusCodes.BadTooManySessions) {
635
- return callback(new Error(response.responseHeader.serviceResult.toString()));
636
- }
637
- if (response.responseHeader.serviceResult !== node_opcua_status_code_1.StatusCodes.Good) {
638
- err = new Error("Error " + response.responseHeader.serviceResult.name + " " + response.responseHeader.serviceResult.description);
639
- return callback(err);
640
- }
641
- // istanbul ignore next
642
- if (!validateServerNonce(response.serverNonce)) {
643
- return callback(new Error("Invalid server Nonce"));
644
- }
645
- // todo: verify SignedSoftwareCertificates and response.serverSignature
646
- session = session || new client_session_impl_1.ClientSessionImpl(this);
647
- session.name = request.sessionName || "";
648
- session.sessionId = response.sessionId;
649
- session.authenticationToken = response.authenticationToken;
650
- session.timeout = _adjustRevisedSessionTimeout(response.revisedSessionTimeout, this.requestedSessionTimeout);
651
- session.serverNonce = response.serverNonce;
652
- session.serverCertificate = response.serverCertificate;
653
- session.serverSignature = response.serverSignature;
654
- debugLog("revised session timeout = ", session.timeout, response.revisedSessionTimeout);
655
- response.serverEndpoints = response.serverEndpoints || [];
656
- if (!verifyEndpointDescriptionMatches(this, response.serverEndpoints)) {
657
- errorLog("Endpoint description previously retrieved with GetEndpointsDescription");
658
- errorLog("CreateSessionResponse.serverEndpoints= ");
659
- errorLog(response.serverEndpoints);
660
- return callback(new Error("Invalid endpoint descriptions Found"));
661
- }
662
- // this._serverEndpoints = response.serverEndpoints;
663
- session.serverEndpoints = response.serverEndpoints;
664
- callback(null, session);
665
- });
666
- }
667
- /**
668
- *
669
- * @internal
670
- * @private
671
- */
672
- __createSession_step2(session, callback) {
673
- (0, util_1.callbackify)(node_opcua_hostname_1.extractFullyQualifiedDomainName)(() => {
674
- this.__createSession_step3(session, callback);
675
- });
676
- }
677
- /**
678
- * @internal
679
- * @private
680
- */
681
- _activateSession(session, callback) {
682
- // see OPCUA Part 4 - $7.35
683
- (0, node_opcua_assert_1.assert)(typeof callback === "function");
684
- // istanbul ignore next
685
- if (!this._secureChannel) {
686
- return callback(new Error(" No secure channel"));
687
- }
688
- const serverCertificate = session.serverCertificate;
689
- // If the securityPolicyUri is None and none of the UserTokenPolicies requires encryption,
690
- // the Client shall ignore the ApplicationInstanceCertificate (serverCertificate)
691
- (0, node_opcua_assert_1.assert)(serverCertificate === null || serverCertificate instanceof Buffer);
692
- const serverNonce = session.serverNonce;
693
- (0, node_opcua_assert_1.assert)(!serverNonce || serverNonce instanceof Buffer);
694
- // make sure session is attached to this client
695
- const _old_client = session._client;
696
- session._client = this;
697
- const context = {
698
- endpoint: this.endpoint,
699
- securityPolicy: this._secureChannel.securityPolicy,
700
- serverCertificate,
701
- serverNonce: serverNonce // please check this !
702
- };
703
- this.createUserIdentityToken(context, this.userIdentityInfo, (err, data) => {
704
- if (err) {
705
- session._client = _old_client;
706
- return callback(err);
707
- }
708
- data = data;
709
- const userIdentityToken = data.userIdentityToken;
710
- const userTokenSignature = data.userTokenSignature;
711
- // TODO. fill the ActivateSessionRequest
712
- // see 5.6.3.2 Parameters OPC Unified Architecture, Part 4 30 Release 1.02
713
- const request = new node_opcua_service_session_1.ActivateSessionRequest({
714
- // This is a signature generated with the private key associated with the
715
- // clientCertificate. The SignatureAlgorithm shall be the AsymmetricSignatureAlgorithm
716
- // specified in the SecurityPolicy for the Endpoint. The SignatureData type is defined in 7.30.
717
- clientSignature: this.computeClientSignature(this._secureChannel, serverCertificate, serverNonce) || undefined,
718
- // These are the SoftwareCertificates which have been issued to the Client application.
719
- // The productUri contained in the SoftwareCertificates shall match the productUri in the
720
- // ApplicationDescription passed by the Client in the CreateSession requests. Certificates without
721
- // matching productUri should be ignored. Servers may reject connections from Clients if they are
722
- // not satisfied with the SoftwareCertificates provided by the Client.
723
- // This parameter only needs to be specified in the first ActivateSession request
724
- // after CreateSession.
725
- // It shall always be omitted if the maxRequestMessageSize returned from the Server in the
726
- // CreateSession response is less than one megabyte.
727
- // The SignedSoftwareCertificate type is defined in 7.31.
728
- clientSoftwareCertificates: [],
729
- // List of locale ids in priority order for localized strings. The first LocaleId in the list
730
- // has the highest priority. If the Server returns a localized string to the Client, the Server
731
- // shall return the translation with the highest priority that it can. If it does not have a
732
- // translation for any of the locales identified in this list, then it shall return the string
733
- // value that it has and include the locale id with the string.
734
- // See Part 3 for more detail on locale ids. If the Client fails to specify at least one locale id,
735
- // the Server shall use any that it has.
736
- // This parameter only needs to be specified during the first call to ActivateSession during
737
- // a single application Session. If it is not specified the Server shall keep using the current
738
- // localeIds for the Session.
739
- localeIds: [],
740
- // The credentials of the user associated with the Client application. The Server uses these
741
- // credentials to determine whether the Client should be allowed to activate a Session and what
742
- // resources the Client has access to during this Session. The UserIdentityToken is an extensible
743
- // parameter type defined in 7.35.
744
- // The EndpointDescription specifies what UserIdentityTokens the Server shall accept.
745
- userIdentityToken,
746
- // If the Client specified a user identity token that supports digital signatures,
747
- // then it shall create a signature and pass it as this parameter. Otherwise the parameter
748
- // is omitted.
749
- // The SignatureAlgorithm depends on the identity token type.
750
- userTokenSignature
751
- });
752
- request.requestHeader.authenticationToken = session.authenticationToken;
753
- session.lastRequestSentTime = new Date();
754
- this.performMessageTransaction(request, (err1, response) => {
755
- if (!err1 && response && response.responseHeader.serviceResult === node_opcua_status_code_1.StatusCodes.Good) {
756
- /* istanbul ignore next */
757
- if (!(response instanceof node_opcua_service_session_1.ActivateSessionResponse)) {
758
- return callback(new Error("Internal Error"));
759
- }
760
- if (!validateServerNonce(response.serverNonce)) {
761
- return callback(new Error("Invalid server Nonce"));
762
- }
763
- session._client = this;
764
- session.serverNonce = response.serverNonce;
765
- session.lastResponseReceivedTime = new Date();
766
- if (this.keepSessionAlive) {
767
- session.startKeepAliveManager();
768
- }
769
- return callback(null, session);
770
- }
771
- else {
772
- // restore client
773
- session._client = _old_client;
774
- /* istanbul ignore next */
775
- if (!err1 && response) {
776
- err1 = new Error(response.responseHeader.serviceResult.toString());
777
- }
778
- session._client = _old_client;
779
- return callback(err1);
780
- }
781
- });
782
- });
783
- }
784
- /**
785
- *
786
- * @private
787
- */
788
- _nextSessionName() {
789
- if (!this.___sessionName_counter) {
790
- this.___sessionName_counter = 0;
791
- }
792
- this.___sessionName_counter += 1;
793
- return this.clientName + this.___sessionName_counter;
794
- }
795
- /**
796
- *
797
- * @private
798
- */
799
- _getApplicationUri() {
800
- var _a, _b;
801
- const certificate = this.getCertificate();
802
- let applicationUri;
803
- if (certificate) {
804
- const e = (0, node_opcua_crypto_1.exploreCertificate)(certificate);
805
- if ((_b = (_a = e.tbsCertificate.extensions) === null || _a === void 0 ? void 0 : _a.subjectAltName) === null || _b === void 0 ? void 0 : _b.uniformResourceIdentifier) {
806
- applicationUri = e.tbsCertificate.extensions.subjectAltName.uniformResourceIdentifier[0];
807
- }
808
- else {
809
- errorLog("Certificate has no extensions.subjectAltName.uniformResourceIdentifier, ");
810
- errorLog((0, node_opcua_crypto_1.toPem)(certificate, "CERTIFICATE"));
811
- applicationUri = this._getBuiltApplicationUri();
812
- }
813
- }
814
- else {
815
- applicationUri = this._getBuiltApplicationUri();
816
- }
817
- return applicationUri;
818
- }
819
- /**
820
- *
821
- * @private
822
- */
823
- __resolveEndPoint() {
824
- this.securityPolicy = this.securityPolicy || node_opcua_secure_channel_1.SecurityPolicy.None;
825
- let endpoint = this.findEndpoint(this._secureChannel.endpointUrl, this.securityMode, this.securityPolicy);
826
- this.endpoint = endpoint;
827
- // this is explained here : see OPCUA Part 4 Version 1.02 $5.4.1 page 12:
828
- // A Client shall verify the HostName specified in the Server Certificate is the same as the HostName
829
- // contained in the endpointUrl provided in the EndpointDescription. If there is a difference then the
830
- // Client shall report the difference and may close the SecureChannel.
831
- if (!this.endpoint) {
832
- if (this.endpointMustExist) {
833
- debugLog("OPCUAClientImpl#endpointMustExist = true and endpoint with url ", this._secureChannel.endpointUrl, " cannot be found");
834
- return false;
835
- }
836
- else {
837
- // fallback :
838
- // our strategy is to take the first server_end_point that match the security settings
839
- // ( is this really OK ?)
840
- // this will permit us to access a OPCUA Server using it's IP address instead of its hostname
841
- endpoint = this.findEndpointForSecurity(this.securityMode, this.securityPolicy);
842
- if (!endpoint) {
843
- return false;
844
- }
845
- this.endpoint = endpoint;
846
- }
847
- }
848
- return true;
849
- }
850
- /**
851
- *
852
- * @private
853
- */
854
- _createSession(callback) {
855
- (0, node_opcua_assert_1.assert)(typeof callback === "function");
856
- (0, node_opcua_assert_1.assert)(this._secureChannel);
857
- if (!this.__resolveEndPoint() || !this.endpoint) {
858
- /* istanbul ignore next */
859
- if (doDebug && this._serverEndpoints) {
860
- debugLog(this._serverEndpoints.map((endpoint) => endpoint.endpointUrl + " " + endpoint.securityMode.toString() + " " + endpoint.securityPolicyUri));
861
- }
862
- return callback(new Error(" End point must exist " + this._secureChannel.endpointUrl));
863
- }
864
- this.serverUri = this.endpoint.server.applicationUri || "invalid application uri";
865
- this.endpointUrl = this._secureChannel.endpointUrl;
866
- const session = new client_session_impl_1.ClientSessionImpl(this);
867
- this.__createSession_step2(session, callback);
868
- }
869
- /**
870
- *
871
- * @private
872
- */
873
- computeClientSignature(channel, serverCertificate, serverNonce) {
874
- return (0, node_opcua_secure_channel_1.computeSignature)(serverCertificate, serverNonce || Buffer.alloc(0), this.getPrivateKey(), channel.securityPolicy);
875
- }
876
- /**
877
- *
878
- * @private
879
- */
880
- createUserIdentityToken(context, userIdentityInfo, callback) {
881
- function coerceUserIdentityInfo(identityInfo) {
882
- if (!identityInfo) {
883
- return { type: node_opcua_service_endpoints_1.UserTokenType.Anonymous };
884
- }
885
- if (Object.prototype.hasOwnProperty.call(identityInfo, "type")) {
886
- return identityInfo;
887
- }
888
- if (Object.prototype.hasOwnProperty.call(identityInfo, "userName")) {
889
- identityInfo.type = node_opcua_service_endpoints_1.UserTokenType.UserName;
890
- return identityInfo;
891
- }
892
- if (Object.prototype.hasOwnProperty.call(identityInfo, "certificateData")) {
893
- identityInfo.type = node_opcua_service_endpoints_1.UserTokenType.Certificate;
894
- return identityInfo;
895
- }
896
- identityInfo.type = node_opcua_service_endpoints_1.UserTokenType.Anonymous;
897
- return identityInfo;
898
- }
899
- userIdentityInfo = coerceUserIdentityInfo(userIdentityInfo);
900
- (0, node_opcua_assert_1.assert)(typeof callback === "function");
901
- if (null === userIdentityInfo) {
902
- return callback(null, {
903
- userIdentityToken: null,
904
- userTokenSignature: {}
905
- });
906
- }
907
- let userIdentityToken;
908
- let userTokenSignature = {
909
- algorithm: undefined,
910
- signature: undefined
911
- };
912
- try {
913
- switch (userIdentityInfo.type) {
914
- case node_opcua_service_endpoints_1.UserTokenType.Anonymous:
915
- userIdentityToken = createAnonymousIdentityToken(context);
916
- break;
917
- case node_opcua_service_endpoints_1.UserTokenType.UserName: {
918
- const userName = userIdentityInfo.userName || "";
919
- const password = userIdentityInfo.password || "";
920
- userIdentityToken = createUserNameIdentityToken(context, userName, password);
921
- break;
922
- }
923
- case node_opcua_service_endpoints_1.UserTokenType.Certificate: {
924
- const certificate = userIdentityInfo.certificateData;
925
- const privateKey = userIdentityInfo.privateKey;
926
- ({ userIdentityToken, userTokenSignature } = createX509IdentityToken(context, certificate, privateKey));
927
- break;
928
- }
929
- default:
930
- debugLog(" userIdentityInfo = ", userIdentityInfo);
931
- return callback(new Error("CLIENT: Invalid userIdentityInfo"));
932
- }
933
- }
934
- catch (err) {
935
- if (typeof err === "string") {
936
- return callback(new Error("Create identity token failed " + userIdentityInfo.type + " " + err));
937
- }
938
- return callback(err);
939
- }
940
- return callback(null, { userIdentityToken, userTokenSignature });
941
- }
942
- }
943
- exports.OPCUAClientImpl = OPCUAClientImpl;
944
- OPCUAClientImpl.minimumRevisedSessionTimeout = 100.0;
945
- // tslint:disable:no-var-requires
946
- // tslint:disable:max-line-length
947
- const thenify = require("thenify");
948
- /**
949
- * @method createSession
950
- * @async
951
- *
952
- * @example
953
- * // create a anonymous session
954
- * const session = await client.createSession();
955
- *
956
- * @example
957
- * // create a session with a userName and password
958
- * const userIdentityInfo = {
959
- * type: UserTokenType.UserName,
960
- * userName: "JoeDoe",
961
- * password:"secret"
962
- * };
963
- * const session = client.createSession(userIdentityInfo);
964
- *
965
- */
966
- OPCUAClientImpl.prototype.createSession = thenify.withCallback(OPCUAClientImpl.prototype.createSession);
967
- OPCUAClientImpl.prototype.createSession2 = thenify.withCallback(OPCUAClientImpl.prototype.createSession2);
968
- /**
969
- * @method changeSessionIdentity
970
- * @async
971
- */
972
- OPCUAClientImpl.prototype.changeSessionIdentity = thenify.withCallback(OPCUAClientImpl.prototype.changeSessionIdentity);
973
- /**
974
- * @method closeSession
975
- * @async
976
- * @example
977
- * const session = await client.createSession();
978
- * await client.closeSession(session);
979
- */
980
- OPCUAClientImpl.prototype.closeSession = thenify.withCallback(OPCUAClientImpl.prototype.closeSession);
981
- OPCUAClientImpl.prototype.reactivateSession = thenify.withCallback(OPCUAClientImpl.prototype.reactivateSession);
1
+ "use strict";
2
+ /**
3
+ * @module node-opcua-client-private
4
+ */
5
+ // tslint:disable:variable-name
6
+ // tslint:disable:no-console
7
+ // tslint:disable:no-empty
8
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
9
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
10
+ return new (P || (P = Promise))(function (resolve, reject) {
11
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
12
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
13
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
14
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
15
+ });
16
+ };
17
+ Object.defineProperty(exports, "__esModule", { value: true });
18
+ exports.OPCUAClientImpl = void 0;
19
+ const crypto = require("crypto");
20
+ const util_1 = require("util");
21
+ const async = require("async");
22
+ const chalk = require("chalk");
23
+ const node_opcua_assert_1 = require("node-opcua-assert");
24
+ const node_opcua_buffer_utils_1 = require("node-opcua-buffer-utils");
25
+ const node_opcua_crypto_1 = require("node-opcua-crypto");
26
+ const node_opcua_data_model_1 = require("node-opcua-data-model");
27
+ const node_opcua_debug_1 = require("node-opcua-debug");
28
+ const node_opcua_hostname_1 = require("node-opcua-hostname");
29
+ const node_opcua_secure_channel_1 = require("node-opcua-secure-channel");
30
+ const node_opcua_service_endpoints_1 = require("node-opcua-service-endpoints");
31
+ const node_opcua_service_secure_channel_1 = require("node-opcua-service-secure-channel");
32
+ const node_opcua_service_session_1 = require("node-opcua-service-session");
33
+ const node_opcua_status_code_1 = require("node-opcua-status-code");
34
+ const node_opcua_utils_1 = require("node-opcua-utils");
35
+ const opcua_client_1 = require("../opcua_client");
36
+ const reconnection_1 = require("../reconnection");
37
+ const client_base_impl_1 = require("./client_base_impl");
38
+ const client_session_impl_1 = require("./client_session_impl");
39
+ const client_subscription_impl_1 = require("./client_subscription_impl");
40
+ const doDebug = (0, node_opcua_debug_1.checkDebugFlag)(__filename);
41
+ const debugLog = (0, node_opcua_debug_1.make_debugLog)(__filename);
42
+ const errorLog = (0, node_opcua_debug_1.make_errorLog)(__filename);
43
+ const warningLog = (0, node_opcua_debug_1.make_warningLog)(__filename);
44
+ function validateServerNonce(serverNonce) {
45
+ return !(serverNonce && serverNonce.length < 32) || (serverNonce && serverNonce.length === 0);
46
+ }
47
+ function verifyEndpointDescriptionMatches(client, responseServerEndpoints) {
48
+ // The Server returns its EndpointDescriptions in the response. Clients use this information to
49
+ // determine whether the list of EndpointDescriptions returned from the Discovery Endpoint matches
50
+ // the Endpoints that the Server has. If there is a difference then the Client shall close the
51
+ // Session and report an error.
52
+ // The Server returns all EndpointDescriptions for the serverUri
53
+ // specified by the Client in the request. The Client only verifies EndpointDescriptions with a
54
+ // transportProfileUri that matches the profileUri specified in the original GetEndpoints request.
55
+ // A Client may skip this check if the EndpointDescriptions were provided by a trusted source
56
+ // such as the Administrator.
57
+ // serverEndpoints:
58
+ // The Client shall verify this list with the list from a Discovery Endpoint if it used a Discovery Endpoint
59
+ // fetch to the EndpointDescriptions.
60
+ // ToDo
61
+ return true;
62
+ }
63
+ function findUserTokenPolicy(endpointDescription, userTokenType) {
64
+ endpointDescription.userIdentityTokens = endpointDescription.userIdentityTokens || [];
65
+ const r = endpointDescription.userIdentityTokens.filter((userIdentity) => userIdentity.tokenType === userTokenType);
66
+ return r.length === 0 ? null : r[0];
67
+ }
68
+ function createAnonymousIdentityToken(context) {
69
+ const endpoint = context.endpoint;
70
+ const userTokenPolicy = findUserTokenPolicy(endpoint, node_opcua_service_endpoints_1.UserTokenType.Anonymous);
71
+ if (!userTokenPolicy) {
72
+ throw new Error("Cannot find ANONYMOUS user token policy in end point description");
73
+ }
74
+ return new node_opcua_service_session_1.AnonymousIdentityToken({ policyId: userTokenPolicy.policyId });
75
+ }
76
+ /**
77
+ *
78
+ * @param context
79
+ * @param certificate - the user certificate
80
+ * @param privateKey - the private key associated with the user certificate
81
+ */
82
+ function createX509IdentityToken(context, certificate, privateKey) {
83
+ const endpoint = context.endpoint;
84
+ (0, node_opcua_assert_1.assert)(endpoint instanceof node_opcua_service_endpoints_1.EndpointDescription);
85
+ const userTokenPolicy = findUserTokenPolicy(endpoint, node_opcua_service_endpoints_1.UserTokenType.Certificate);
86
+ // istanbul ignore next
87
+ if (!userTokenPolicy) {
88
+ throw new Error("Cannot find Certificate (X509) user token policy in end point description");
89
+ }
90
+ let securityPolicy = (0, node_opcua_secure_channel_1.fromURI)(userTokenPolicy.securityPolicyUri);
91
+ // if the security policy is not specified we use the session security policy
92
+ if (securityPolicy === node_opcua_secure_channel_1.SecurityPolicy.Invalid) {
93
+ securityPolicy = context.securityPolicy;
94
+ }
95
+ const userIdentityToken = new node_opcua_service_session_1.X509IdentityToken({
96
+ certificateData: certificate,
97
+ policyId: userTokenPolicy.policyId
98
+ });
99
+ const serverCertificate = context.serverCertificate;
100
+ (0, node_opcua_assert_1.assert)(serverCertificate instanceof Buffer);
101
+ const serverNonce = context.serverNonce || Buffer.alloc(0);
102
+ (0, node_opcua_assert_1.assert)(serverNonce instanceof Buffer);
103
+ // see Release 1.02 155 OPC Unified Architecture, Part 4
104
+ const cryptoFactory = (0, node_opcua_secure_channel_1.getCryptoFactory)(securityPolicy);
105
+ // istanbul ignore next
106
+ if (!cryptoFactory) {
107
+ throw new Error(" Unsupported security Policy");
108
+ }
109
+ /**
110
+ * OPCUA Spec 1.04 - part 4
111
+ * page 28:
112
+ * 5.6.3.1
113
+ * ...
114
+ * If the token is an X509IdentityToken then the proof is a signature generated with private key
115
+ * associated with the Certificate. The data to sign is created by appending the last serverNonce to
116
+ * the **serverCertificate** specified in the CreateSession response. If a token includes a secret then it
117
+ * should be encrypted using the public key from the serverCertificate.
118
+ *
119
+ * page 155:
120
+ * Token Encryption and Proof of Possession
121
+ * 7.36.2.1 Overview
122
+ * The Client shall always prove possession of a UserIdentityToken when it passes it to the Server.
123
+ * Some tokens include a secret such as a password which the Server will accept as proof. In order
124
+ * to protect these secrets the Token may be encrypted before it is passed to the Server. Other types
125
+ * of tokens allow the Client to create a signature with the secret associated with the Token. In these
126
+ * cases, the Client proves possession of a UserIdentityToken by creating a signature with the secret
127
+ * and passing it to the Server
128
+ *
129
+ * page 159:
130
+ * 7.36.5 X509IdentityTokens
131
+ * The X509IdentityToken is used to pass an X.509 v3 Certificate which is issued by the user.
132
+ * This token shall always be accompanied by a Signature in the userTokenSignature parameter of
133
+ * ActivateSession if required by the SecurityPolicy. The Server should specify a SecurityPolicy for
134
+ * the UserTokenPolicy if the SecureChannel has a SecurityPolicy of None.
135
+ */
136
+ // now create the proof of possession, by creating a signature
137
+ // The data to sign is created by appending the last serverNonce to the serverCertificate
138
+ // The signature generated with private key associated with the User Certificate
139
+ const userTokenSignature = (0, node_opcua_secure_channel_1.computeSignature)(serverCertificate, serverNonce, privateKey, securityPolicy);
140
+ return { userIdentityToken, userTokenSignature };
141
+ }
142
+ function createUserNameIdentityToken(session, userName, password) {
143
+ // assert(endpoint instanceof EndpointDescription);
144
+ (0, node_opcua_assert_1.assert)(userName === null || typeof userName === "string");
145
+ (0, node_opcua_assert_1.assert)(password === null || typeof password === "string");
146
+ const endpoint = session.endpoint;
147
+ (0, node_opcua_assert_1.assert)(endpoint instanceof node_opcua_service_endpoints_1.EndpointDescription);
148
+ /**
149
+ * OPC Unified Architecture 1.0.4: Part 4 155
150
+ * Each UserIdentityToken allowed by an Endpoint shall have a UserTokenPolicy specified in the
151
+ * EndpointDescription. The UserTokenPolicy specifies what SecurityPolicy to use when encrypting
152
+ * or signing. If this SecurityPolicy is omitted then the Client uses the SecurityPolicy in the
153
+ * EndpointDescription. If the matching SecurityPolicy is set to None then no encryption or signature
154
+ * is required.
155
+ *
156
+ */
157
+ const userTokenPolicy = findUserTokenPolicy(endpoint, node_opcua_service_endpoints_1.UserTokenType.UserName);
158
+ // istanbul ignore next
159
+ if (!userTokenPolicy) {
160
+ throw new Error("Cannot find USERNAME user token policy in end point description");
161
+ }
162
+ let securityPolicy = (0, node_opcua_secure_channel_1.fromURI)(userTokenPolicy.securityPolicyUri);
163
+ // if the security policy is not specified we use the session security policy
164
+ if (securityPolicy === node_opcua_secure_channel_1.SecurityPolicy.Invalid) {
165
+ securityPolicy = session.securityPolicy;
166
+ }
167
+ let identityToken;
168
+ let serverCertificate = session.serverCertificate;
169
+ // if server does not provide certificate use unencrypted password
170
+ if (!serverCertificate) {
171
+ identityToken = new node_opcua_service_session_1.UserNameIdentityToken({
172
+ encryptionAlgorithm: null,
173
+ password: Buffer.from(password, "utf-8"),
174
+ policyId: userTokenPolicy ? userTokenPolicy.policyId : null,
175
+ userName
176
+ });
177
+ return identityToken;
178
+ }
179
+ (0, node_opcua_assert_1.assert)(serverCertificate instanceof Buffer);
180
+ serverCertificate = (0, node_opcua_crypto_1.toPem)(serverCertificate, "CERTIFICATE");
181
+ const publicKey = (0, node_opcua_crypto_1.extractPublicKeyFromCertificateSync)(serverCertificate);
182
+ const serverNonce = session.serverNonce || Buffer.alloc(0);
183
+ (0, node_opcua_assert_1.assert)(serverNonce instanceof Buffer);
184
+ // If None is specified for the UserTokenPolicy and SecurityPolicy is None
185
+ // then the password only contains the UTF-8 encoded password.
186
+ // note: this means that password is sent in clear text to the server
187
+ // note: OPCUA specification discourages use of unencrypted password
188
+ // but some old OPCUA server may only provide this policy and we
189
+ // still have to support in the client?
190
+ if (securityPolicy === node_opcua_secure_channel_1.SecurityPolicy.None) {
191
+ identityToken = new node_opcua_service_session_1.UserNameIdentityToken({
192
+ encryptionAlgorithm: null,
193
+ password: Buffer.from(password, "utf-8"),
194
+ policyId: userTokenPolicy.policyId,
195
+ userName
196
+ });
197
+ return identityToken;
198
+ }
199
+ // see Release 1.02 155 OPC Unified Architecture, Part 4
200
+ const cryptoFactory = (0, node_opcua_secure_channel_1.getCryptoFactory)(securityPolicy);
201
+ // istanbul ignore next
202
+ if (!cryptoFactory) {
203
+ throw new Error(" Unsupported security Policy " + securityPolicy.toString());
204
+ }
205
+ identityToken = new node_opcua_service_session_1.UserNameIdentityToken({
206
+ encryptionAlgorithm: cryptoFactory.asymmetricEncryptionAlgorithm,
207
+ password: Buffer.from(password, "utf-8"),
208
+ policyId: userTokenPolicy.policyId,
209
+ userName
210
+ });
211
+ // now encrypt password as requested
212
+ const lenBuf = (0, node_opcua_buffer_utils_1.createFastUninitializedBuffer)(4);
213
+ lenBuf.writeUInt32LE(identityToken.password.length + serverNonce.length, 0);
214
+ const block = Buffer.concat([lenBuf, identityToken.password, serverNonce]);
215
+ identityToken.password = cryptoFactory.asymmetricEncrypt(block, publicKey);
216
+ return identityToken;
217
+ }
218
+ function _adjustRevisedSessionTimeout(revisedSessionTimeout, requestedTimeout) {
219
+ // Some old OPCUA Servers are known to report an invalid revisedSessionTimeout
220
+ // such as Siemens SimoCode Pro V.
221
+ // we need to adjust the value here, by guessing a sensible sessionTimeout value to use instead.
222
+ if (revisedSessionTimeout < 1e-10) {
223
+ warningLog(`the revisedSessionTimeout ${revisedSessionTimeout} reported by the server is inconsistent and has been adjusted back to requestedTimeout ${requestedTimeout}`);
224
+ return requestedTimeout;
225
+ }
226
+ if (revisedSessionTimeout < OPCUAClientImpl.minimumRevisedSessionTimeout) {
227
+ warningLog(`the revisedSessionTimeout ${revisedSessionTimeout} is smaller than the minimum timeout (OPCUAClientImpl.minimumRevisedSessionTimeout = ${OPCUAClientImpl.minimumRevisedSessionTimeout}) and has been clamped to this value`);
228
+ return OPCUAClientImpl.minimumRevisedSessionTimeout;
229
+ }
230
+ return revisedSessionTimeout;
231
+ }
232
+ /***
233
+ * @constructor
234
+ * @internal
235
+ */
236
+ class OPCUAClientImpl extends client_base_impl_1.ClientBaseImpl {
237
+ constructor(options) {
238
+ options = options || {};
239
+ super(options);
240
+ // @property endpointMustExist {Boolean}
241
+ // if set to true , create Session will only accept connection from server which endpoint_url has been reported
242
+ // by GetEndpointsRequest.
243
+ // By default, the client is strict.
244
+ if (Object.prototype.hasOwnProperty.call(options, "endpoint_must_exist")) {
245
+ if (Object.prototype.hasOwnProperty.call(options, "endpointMustExist")) {
246
+ throw new Error("endpoint_must_exist is deprecated! you must now use endpointMustExist instead of endpoint_must_exist ");
247
+ }
248
+ warningLog("Warning: endpoint_must_exist is now deprecated, use endpointMustExist instead");
249
+ options.endpointMustExist = options.endpoint_must_exist;
250
+ }
251
+ this.endpointMustExist = (0, node_opcua_utils_1.isNullOrUndefined)(options.endpointMustExist) ? true : !!options.endpointMustExist;
252
+ this.requestedSessionTimeout = options.requestedSessionTimeout || 60000; // 1 minute
253
+ this.___sessionName_counter = 0;
254
+ this.userIdentityInfo = { type: node_opcua_service_endpoints_1.UserTokenType.Anonymous };
255
+ this.endpoint = undefined;
256
+ }
257
+ static create(options) {
258
+ return new OPCUAClientImpl(options);
259
+ }
260
+ /**
261
+ * @internal
262
+ * @param args
263
+ *
264
+ */
265
+ createSession(...args) {
266
+ if (args.length === 1) {
267
+ return this.createSession({ type: node_opcua_service_endpoints_1.UserTokenType.Anonymous }, args[0]);
268
+ }
269
+ const userIdentityInfo = args[0] || { type: node_opcua_service_endpoints_1.UserTokenType.Anonymous };
270
+ const callback = args[1];
271
+ this.userIdentityInfo = userIdentityInfo;
272
+ (0, node_opcua_assert_1.assert)(typeof callback === "function");
273
+ this._createSession((err, session) => {
274
+ if (err) {
275
+ callback(err);
276
+ }
277
+ else {
278
+ /* istanbul ignore next */
279
+ if (!session) {
280
+ return callback(new Error("Internal Error"));
281
+ }
282
+ this._addSession(session);
283
+ this._activateSession(session, (err1, session2) => {
284
+ callback(err1, session2);
285
+ });
286
+ }
287
+ });
288
+ }
289
+ createSession2(...args) {
290
+ if (args.length === 1) {
291
+ return this.createSession2({ type: node_opcua_service_endpoints_1.UserTokenType.Anonymous }, args[0]);
292
+ }
293
+ const userIdentityInfo = args[0];
294
+ const callback = args[1];
295
+ if (!this._secureChannel) {
296
+ // we do not have a connection anymore
297
+ return callback(new Error("Connection is closed"));
298
+ }
299
+ return this.createSession(args[0], (err, session) => {
300
+ if (err && err.message.match(/BadTooManySessions/)) {
301
+ const delayToRetry = 5; // seconds
302
+ errorLog(`TooManySession .... we need to retry later ... in ${delayToRetry} secondes`);
303
+ const retryCreateSessionTimer = setTimeout(() => {
304
+ errorLog("TooManySession .... now retrying");
305
+ this.createSession2(userIdentityInfo, callback);
306
+ }, delayToRetry * 1000);
307
+ return;
308
+ }
309
+ callback(err, session);
310
+ });
311
+ }
312
+ /**
313
+ * @internal
314
+ * @param args
315
+ */
316
+ changeSessionIdentity(...args) {
317
+ const session = args[0];
318
+ const userIdentityInfo = args[1];
319
+ const callback = args[2];
320
+ (0, node_opcua_assert_1.assert)(typeof callback === "function");
321
+ const old_userIdentity = this.userIdentityInfo;
322
+ this.userIdentityInfo = userIdentityInfo;
323
+ this._activateSession(session, (err1, session1) => {
324
+ callback(err1 ? err1 : undefined);
325
+ });
326
+ }
327
+ /**
328
+ * @internals
329
+ * @param args
330
+ */
331
+ closeSession(...args) {
332
+ super.closeSession(...args);
333
+ }
334
+ toString() {
335
+ let str = client_base_impl_1.ClientBaseImpl.prototype.toString.call(this);
336
+ str += " requestedSessionTimeout....... " + this.requestedSessionTimeout + "\n";
337
+ str += " endpointUrl................... " + this.endpointUrl + "\n";
338
+ str += " serverUri..................... " + this.serverUri + "\n";
339
+ return str;
340
+ }
341
+ /**
342
+ *
343
+ * @example
344
+ *
345
+ * ```javascript
346
+ *
347
+ * const session = await OPCUAClient.createSession(endpointUrl);
348
+ * const dataValue = await session.read({ nodeId, attributeId: AttributeIds.Value });
349
+ * await session.close();
350
+ *
351
+ * ```
352
+ * @stability experimental
353
+ *
354
+ * @param endpointUrl
355
+ * @param userIdentity
356
+ * @returns session
357
+ *
358
+ *
359
+ * const create
360
+ */
361
+ static createSession(endpointUrl, userIdentity, clientOptions) {
362
+ return __awaiter(this, void 0, void 0, function* () {
363
+ const client = opcua_client_1.OPCUAClient.create(clientOptions || {});
364
+ yield client.connect(endpointUrl);
365
+ const session = yield client.createSession2(userIdentity);
366
+ const oldClose = session.close;
367
+ session.close = thenify.withCallback((...args) => {
368
+ if (args.length === 1) {
369
+ return session.close(true, args[0]);
370
+ }
371
+ const deleteSubscriptions = args[0];
372
+ const callback = args[1];
373
+ session.close = oldClose;
374
+ oldClose.call(session, deleteSubscriptions, (err) => {
375
+ client.disconnect((err) => {
376
+ callback(err);
377
+ });
378
+ });
379
+ });
380
+ return session;
381
+ });
382
+ }
383
+ /**
384
+ * @internal
385
+ * @param args
386
+ */
387
+ withSession(connectionPoint, inner_func, ...args) {
388
+ const endpointUrl = typeof connectionPoint === "string" ? connectionPoint : connectionPoint.endpointUrl;
389
+ const userIdentity = typeof connectionPoint === "string" ? { type: node_opcua_service_endpoints_1.UserTokenType.Anonymous } : connectionPoint.userIdentity;
390
+ const callback = args[0];
391
+ (0, node_opcua_assert_1.assert)(typeof inner_func === "function", "expecting inner function");
392
+ (0, node_opcua_assert_1.assert)(typeof callback === "function", "expecting callback function");
393
+ let theSession;
394
+ let the_error;
395
+ let need_disconnect = false;
396
+ async.series([
397
+ // step 1 : connect to
398
+ (innerCallback) => {
399
+ this.connect(endpointUrl, (err) => {
400
+ need_disconnect = true;
401
+ if (err) {
402
+ warningLog(err.message);
403
+ errorLog(" cannot connect to endpoint :", endpointUrl);
404
+ }
405
+ innerCallback(err);
406
+ });
407
+ },
408
+ // step 2 : createSession
409
+ (innerCallback) => {
410
+ this.createSession2(userIdentity, (err, session) => {
411
+ if (err) {
412
+ return innerCallback(err);
413
+ }
414
+ if (!session) {
415
+ return innerCallback(new Error("internal error"));
416
+ }
417
+ theSession = session;
418
+ innerCallback();
419
+ });
420
+ },
421
+ (innerCallback) => {
422
+ try {
423
+ inner_func(theSession, (err) => {
424
+ the_error = err;
425
+ innerCallback();
426
+ });
427
+ }
428
+ catch (err) {
429
+ console.log("Exception catch in inner function, check your code ", err);
430
+ errorLog("OPCUAClientImpl#withClientSession", err.message);
431
+ the_error = err;
432
+ innerCallback();
433
+ }
434
+ },
435
+ // close session
436
+ (innerCallback) => {
437
+ theSession.close(/*deleteSubscriptions=*/ true, (err) => {
438
+ if (err) {
439
+ debugLog("OPCUAClientImpl#withClientSession: session closed failed ?");
440
+ }
441
+ innerCallback();
442
+ });
443
+ },
444
+ (innerCallback) => {
445
+ this.disconnect((err) => {
446
+ need_disconnect = false;
447
+ if (err) {
448
+ errorLog("OPCUAClientImpl#withClientSession: client disconnect failed ?");
449
+ }
450
+ innerCallback();
451
+ });
452
+ }
453
+ ], (err1) => {
454
+ if (err1) {
455
+ console.log("err", err1.message);
456
+ }
457
+ if (need_disconnect) {
458
+ errorLog("Disconnecting client after failure");
459
+ this.disconnect((err2) => {
460
+ return callback(the_error || err1 || err2);
461
+ });
462
+ }
463
+ else {
464
+ return callback(the_error || err1);
465
+ }
466
+ });
467
+ }
468
+ withSubscription(endpointUrl, subscriptionParameters, innerFunc, callback) {
469
+ (0, node_opcua_assert_1.assert)(typeof innerFunc === "function");
470
+ (0, node_opcua_assert_1.assert)(typeof callback === "function");
471
+ this.withSession(endpointUrl, (session, done) => {
472
+ (0, node_opcua_assert_1.assert)(typeof done === "function");
473
+ const subscription = new client_subscription_impl_1.ClientSubscriptionImpl(session, subscriptionParameters);
474
+ try {
475
+ innerFunc(session, subscription, (err) => {
476
+ subscription.terminate((err1) => {
477
+ done(err1);
478
+ });
479
+ });
480
+ }
481
+ catch (err) {
482
+ debugLog(err);
483
+ done(err);
484
+ }
485
+ }, callback);
486
+ }
487
+ withSessionAsync(connectionPoint, func) {
488
+ return __awaiter(this, void 0, void 0, function* () {
489
+ (0, node_opcua_assert_1.assert)(typeof func === "function");
490
+ (0, node_opcua_assert_1.assert)(func.length === 1, "expecting a single argument in func");
491
+ const endpointUrl = typeof connectionPoint === "string" ? connectionPoint : connectionPoint.endpointUrl;
492
+ const userIdentity = typeof connectionPoint === "string" ? { type: node_opcua_service_endpoints_1.UserTokenType.Anonymous } : connectionPoint.userIdentity;
493
+ yield this.connect(endpointUrl);
494
+ const session = yield this.createSession2(userIdentity);
495
+ let result;
496
+ try {
497
+ result = yield func(session);
498
+ }
499
+ catch (err) {
500
+ errorLog(err);
501
+ throw err;
502
+ }
503
+ finally {
504
+ yield session.close();
505
+ yield this.disconnect();
506
+ }
507
+ return result;
508
+ });
509
+ }
510
+ withSubscriptionAsync(connectionPoint, parameters, func) {
511
+ return __awaiter(this, void 0, void 0, function* () {
512
+ yield this.withSessionAsync(connectionPoint, (session) => __awaiter(this, void 0, void 0, function* () {
513
+ (0, node_opcua_assert_1.assert)(session, " session must exist");
514
+ const subscription = yield session.createSubscription2(parameters);
515
+ try {
516
+ const result = yield func(session, subscription);
517
+ return result;
518
+ }
519
+ catch (err) {
520
+ console.log("withSubscriptionAsync inner function failed ", err.message);
521
+ throw err;
522
+ }
523
+ finally {
524
+ yield subscription.terminate();
525
+ }
526
+ }));
527
+ });
528
+ }
529
+ reactivateSession(session, callback) {
530
+ const internalSession = session;
531
+ (0, node_opcua_assert_1.assert)(typeof callback === "function");
532
+ if (!this._secureChannel) {
533
+ return callback(new Error(" client must be connected first"));
534
+ }
535
+ // istanbul ignore next
536
+ if (!this.__resolveEndPoint() || !this.endpoint) {
537
+ return callback(new Error(" End point must exist " + this._secureChannel.endpointUrl));
538
+ }
539
+ (0, node_opcua_assert_1.assert)(!internalSession._client || (0, node_opcua_utils_1.matchUri)(internalSession._client.endpointUrl, this.endpointUrl), "cannot reactivateSession on a different endpoint");
540
+ const old_client = internalSession._client;
541
+ debugLog("OPCUAClientImpl#reactivateSession");
542
+ this._activateSession(internalSession, (err /*, newSession?: ClientSessionImpl*/) => {
543
+ if (!err) {
544
+ if (old_client !== this) {
545
+ // remove session from old client:
546
+ if (old_client) {
547
+ old_client._removeSession(internalSession);
548
+ (0, node_opcua_assert_1.assert)(old_client._sessions.indexOf(internalSession) === -1);
549
+ }
550
+ this._addSession(internalSession);
551
+ (0, node_opcua_assert_1.assert)(internalSession._client === this);
552
+ (0, node_opcua_assert_1.assert)(!internalSession._closed, "session should not vbe closed");
553
+ (0, node_opcua_assert_1.assert)(this._sessions.indexOf(internalSession) !== -1);
554
+ }
555
+ callback();
556
+ }
557
+ else {
558
+ // istanbul ignore next
559
+ if (doDebug) {
560
+ debugLog(chalk.red.bgWhite("reactivateSession has failed !"), err.message);
561
+ }
562
+ callback(err);
563
+ }
564
+ });
565
+ }
566
+ /**
567
+ * @internal
568
+ * @private
569
+ */
570
+ _on_connection_reestablished(callback) {
571
+ (0, node_opcua_assert_1.assert)(typeof callback === "function");
572
+ // call base class implementation first
573
+ client_base_impl_1.ClientBaseImpl.prototype._on_connection_reestablished.call(this, ( /*err?: Error*/) => {
574
+ (0, reconnection_1.repair_client_sessions)(this, callback);
575
+ });
576
+ }
577
+ /**
578
+ *
579
+ * @internal
580
+ * @private
581
+ */
582
+ __createSession_step3(session, callback) {
583
+ (0, node_opcua_assert_1.assert)(typeof callback === "function");
584
+ (0, node_opcua_assert_1.assert)(this.serverUri !== undefined, " must have a valid server URI " + this.serverUri);
585
+ (0, node_opcua_assert_1.assert)(this.endpointUrl !== undefined, " must have a valid server endpointUrl");
586
+ (0, node_opcua_assert_1.assert)(this.endpoint);
587
+ // istanbul ignore next
588
+ if (!this._secureChannel) {
589
+ return callback(new Error("Invalid channel"));
590
+ }
591
+ const applicationUri = this._getApplicationUri();
592
+ const applicationDescription = {
593
+ applicationName: new node_opcua_data_model_1.LocalizedText({ text: this.applicationName, locale: null }),
594
+ applicationType: node_opcua_service_endpoints_1.ApplicationType.Client,
595
+ applicationUri,
596
+ discoveryProfileUri: undefined,
597
+ discoveryUrls: [],
598
+ gatewayServerUri: undefined,
599
+ productUri: "NodeOPCUA-Client"
600
+ };
601
+ // note : do not confuse CreateSessionRequest.clientNonce with OpenSecureChannelRequest.clientNonce
602
+ // which are two different nonce, with different size (although they share the same name )
603
+ this.clientNonce = crypto.randomBytes(32);
604
+ const request = new node_opcua_service_session_1.CreateSessionRequest({
605
+ clientCertificate: this.getCertificate(),
606
+ clientDescription: applicationDescription,
607
+ clientNonce: this.clientNonce,
608
+ endpointUrl: this.endpointUrl,
609
+ maxResponseMessageSize: 800000,
610
+ requestedSessionTimeout: this.requestedSessionTimeout,
611
+ serverUri: this.serverUri,
612
+ sessionName: this._nextSessionName()
613
+ });
614
+ // a client Nonce must be provided if security mode is set
615
+ (0, node_opcua_assert_1.assert)(this._secureChannel.securityMode === node_opcua_service_secure_channel_1.MessageSecurityMode.None || request.clientNonce !== null);
616
+ this.performMessageTransaction(request, (err, response) => {
617
+ /* istanbul ignore next */
618
+ if (err) {
619
+ console.log("__createSession_step3 has failed", err.message);
620
+ return callback(err);
621
+ // //xxxxxx qdqsdqsdqsdqsd
622
+ // // we could have an invalid state here or a connection error
623
+ // errorLog("error: ", err.message, " retrying in ... 5 secondes");
624
+ // setTimeout(() => {
625
+ // errorLog(" .... now retrying");
626
+ // this.__createSession_step3(session, callback);
627
+ // }, 5 * 1000);
628
+ // return;
629
+ }
630
+ /* istanbul ignore next */
631
+ if (!response || !(response instanceof node_opcua_service_session_1.CreateSessionResponse)) {
632
+ return callback(new Error("internal error"));
633
+ }
634
+ if (response.responseHeader.serviceResult === node_opcua_status_code_1.StatusCodes.BadTooManySessions) {
635
+ return callback(new Error(response.responseHeader.serviceResult.toString()));
636
+ }
637
+ if (response.responseHeader.serviceResult !== node_opcua_status_code_1.StatusCodes.Good) {
638
+ err = new Error("Error " + response.responseHeader.serviceResult.name + " " + response.responseHeader.serviceResult.description);
639
+ return callback(err);
640
+ }
641
+ // istanbul ignore next
642
+ if (!validateServerNonce(response.serverNonce)) {
643
+ return callback(new Error("Invalid server Nonce"));
644
+ }
645
+ // todo: verify SignedSoftwareCertificates and response.serverSignature
646
+ session = session || new client_session_impl_1.ClientSessionImpl(this);
647
+ session.name = request.sessionName || "";
648
+ session.sessionId = response.sessionId;
649
+ session.authenticationToken = response.authenticationToken;
650
+ session.timeout = _adjustRevisedSessionTimeout(response.revisedSessionTimeout, this.requestedSessionTimeout);
651
+ session.serverNonce = response.serverNonce;
652
+ session.serverCertificate = response.serverCertificate;
653
+ session.serverSignature = response.serverSignature;
654
+ debugLog("revised session timeout = ", session.timeout, response.revisedSessionTimeout);
655
+ response.serverEndpoints = response.serverEndpoints || [];
656
+ if (!verifyEndpointDescriptionMatches(this, response.serverEndpoints)) {
657
+ errorLog("Endpoint description previously retrieved with GetEndpointsDescription");
658
+ errorLog("CreateSessionResponse.serverEndpoints= ");
659
+ errorLog(response.serverEndpoints);
660
+ return callback(new Error("Invalid endpoint descriptions Found"));
661
+ }
662
+ // this._serverEndpoints = response.serverEndpoints;
663
+ session.serverEndpoints = response.serverEndpoints;
664
+ callback(null, session);
665
+ });
666
+ }
667
+ /**
668
+ *
669
+ * @internal
670
+ * @private
671
+ */
672
+ __createSession_step2(session, callback) {
673
+ (0, util_1.callbackify)(node_opcua_hostname_1.extractFullyQualifiedDomainName)(() => {
674
+ this.__createSession_step3(session, callback);
675
+ });
676
+ }
677
+ /**
678
+ * @internal
679
+ * @private
680
+ */
681
+ _activateSession(session, callback) {
682
+ // see OPCUA Part 4 - $7.35
683
+ (0, node_opcua_assert_1.assert)(typeof callback === "function");
684
+ // istanbul ignore next
685
+ if (!this._secureChannel) {
686
+ return callback(new Error(" No secure channel"));
687
+ }
688
+ const serverCertificate = session.serverCertificate;
689
+ // If the securityPolicyUri is None and none of the UserTokenPolicies requires encryption,
690
+ // the Client shall ignore the ApplicationInstanceCertificate (serverCertificate)
691
+ (0, node_opcua_assert_1.assert)(serverCertificate === null || serverCertificate instanceof Buffer);
692
+ const serverNonce = session.serverNonce;
693
+ (0, node_opcua_assert_1.assert)(!serverNonce || serverNonce instanceof Buffer);
694
+ // make sure session is attached to this client
695
+ const _old_client = session._client;
696
+ session._client = this;
697
+ const context = {
698
+ endpoint: this.endpoint,
699
+ securityPolicy: this._secureChannel.securityPolicy,
700
+ serverCertificate,
701
+ serverNonce: serverNonce // please check this !
702
+ };
703
+ this.createUserIdentityToken(context, this.userIdentityInfo, (err, data) => {
704
+ if (err) {
705
+ session._client = _old_client;
706
+ return callback(err);
707
+ }
708
+ data = data;
709
+ const userIdentityToken = data.userIdentityToken;
710
+ const userTokenSignature = data.userTokenSignature;
711
+ // TODO. fill the ActivateSessionRequest
712
+ // see 5.6.3.2 Parameters OPC Unified Architecture, Part 4 30 Release 1.02
713
+ const request = new node_opcua_service_session_1.ActivateSessionRequest({
714
+ // This is a signature generated with the private key associated with the
715
+ // clientCertificate. The SignatureAlgorithm shall be the AsymmetricSignatureAlgorithm
716
+ // specified in the SecurityPolicy for the Endpoint. The SignatureData type is defined in 7.30.
717
+ clientSignature: this.computeClientSignature(this._secureChannel, serverCertificate, serverNonce) || undefined,
718
+ // These are the SoftwareCertificates which have been issued to the Client application.
719
+ // The productUri contained in the SoftwareCertificates shall match the productUri in the
720
+ // ApplicationDescription passed by the Client in the CreateSession requests. Certificates without
721
+ // matching productUri should be ignored. Servers may reject connections from Clients if they are
722
+ // not satisfied with the SoftwareCertificates provided by the Client.
723
+ // This parameter only needs to be specified in the first ActivateSession request
724
+ // after CreateSession.
725
+ // It shall always be omitted if the maxRequestMessageSize returned from the Server in the
726
+ // CreateSession response is less than one megabyte.
727
+ // The SignedSoftwareCertificate type is defined in 7.31.
728
+ clientSoftwareCertificates: [],
729
+ // List of locale ids in priority order for localized strings. The first LocaleId in the list
730
+ // has the highest priority. If the Server returns a localized string to the Client, the Server
731
+ // shall return the translation with the highest priority that it can. If it does not have a
732
+ // translation for any of the locales identified in this list, then it shall return the string
733
+ // value that it has and include the locale id with the string.
734
+ // See Part 3 for more detail on locale ids. If the Client fails to specify at least one locale id,
735
+ // the Server shall use any that it has.
736
+ // This parameter only needs to be specified during the first call to ActivateSession during
737
+ // a single application Session. If it is not specified the Server shall keep using the current
738
+ // localeIds for the Session.
739
+ localeIds: [],
740
+ // The credentials of the user associated with the Client application. The Server uses these
741
+ // credentials to determine whether the Client should be allowed to activate a Session and what
742
+ // resources the Client has access to during this Session. The UserIdentityToken is an extensible
743
+ // parameter type defined in 7.35.
744
+ // The EndpointDescription specifies what UserIdentityTokens the Server shall accept.
745
+ userIdentityToken,
746
+ // If the Client specified a user identity token that supports digital signatures,
747
+ // then it shall create a signature and pass it as this parameter. Otherwise the parameter
748
+ // is omitted.
749
+ // The SignatureAlgorithm depends on the identity token type.
750
+ userTokenSignature
751
+ });
752
+ request.requestHeader.authenticationToken = session.authenticationToken;
753
+ session.lastRequestSentTime = new Date();
754
+ this.performMessageTransaction(request, (err1, response) => {
755
+ if (!err1 && response && response.responseHeader.serviceResult === node_opcua_status_code_1.StatusCodes.Good) {
756
+ /* istanbul ignore next */
757
+ if (!(response instanceof node_opcua_service_session_1.ActivateSessionResponse)) {
758
+ return callback(new Error("Internal Error"));
759
+ }
760
+ if (!validateServerNonce(response.serverNonce)) {
761
+ return callback(new Error("Invalid server Nonce"));
762
+ }
763
+ session._client = this;
764
+ session.serverNonce = response.serverNonce;
765
+ session.lastResponseReceivedTime = new Date();
766
+ if (this.keepSessionAlive) {
767
+ session.startKeepAliveManager();
768
+ }
769
+ return callback(null, session);
770
+ }
771
+ else {
772
+ // restore client
773
+ session._client = _old_client;
774
+ /* istanbul ignore next */
775
+ if (!err1 && response) {
776
+ err1 = new Error(response.responseHeader.serviceResult.toString());
777
+ }
778
+ session._client = _old_client;
779
+ return callback(err1);
780
+ }
781
+ });
782
+ });
783
+ }
784
+ /**
785
+ *
786
+ * @private
787
+ */
788
+ _nextSessionName() {
789
+ if (!this.___sessionName_counter) {
790
+ this.___sessionName_counter = 0;
791
+ }
792
+ this.___sessionName_counter += 1;
793
+ return this.clientName + this.___sessionName_counter;
794
+ }
795
+ /**
796
+ *
797
+ * @private
798
+ */
799
+ _getApplicationUri() {
800
+ var _a, _b;
801
+ const certificate = this.getCertificate();
802
+ let applicationUri;
803
+ if (certificate) {
804
+ const e = (0, node_opcua_crypto_1.exploreCertificate)(certificate);
805
+ if ((_b = (_a = e.tbsCertificate.extensions) === null || _a === void 0 ? void 0 : _a.subjectAltName) === null || _b === void 0 ? void 0 : _b.uniformResourceIdentifier) {
806
+ applicationUri = e.tbsCertificate.extensions.subjectAltName.uniformResourceIdentifier[0];
807
+ }
808
+ else {
809
+ errorLog("Certificate has no extensions.subjectAltName.uniformResourceIdentifier, ");
810
+ errorLog((0, node_opcua_crypto_1.toPem)(certificate, "CERTIFICATE"));
811
+ applicationUri = this._getBuiltApplicationUri();
812
+ }
813
+ }
814
+ else {
815
+ applicationUri = this._getBuiltApplicationUri();
816
+ }
817
+ return applicationUri;
818
+ }
819
+ /**
820
+ *
821
+ * @private
822
+ */
823
+ __resolveEndPoint() {
824
+ this.securityPolicy = this.securityPolicy || node_opcua_secure_channel_1.SecurityPolicy.None;
825
+ let endpoint = this.findEndpoint(this._secureChannel.endpointUrl, this.securityMode, this.securityPolicy);
826
+ this.endpoint = endpoint;
827
+ // this is explained here : see OPCUA Part 4 Version 1.02 $5.4.1 page 12:
828
+ // A Client shall verify the HostName specified in the Server Certificate is the same as the HostName
829
+ // contained in the endpointUrl provided in the EndpointDescription. If there is a difference then the
830
+ // Client shall report the difference and may close the SecureChannel.
831
+ if (!this.endpoint) {
832
+ if (this.endpointMustExist) {
833
+ debugLog("OPCUAClientImpl#endpointMustExist = true and endpoint with url ", this._secureChannel.endpointUrl, " cannot be found");
834
+ return false;
835
+ }
836
+ else {
837
+ // fallback :
838
+ // our strategy is to take the first server_end_point that match the security settings
839
+ // ( is this really OK ?)
840
+ // this will permit us to access a OPCUA Server using it's IP address instead of its hostname
841
+ endpoint = this.findEndpointForSecurity(this.securityMode, this.securityPolicy);
842
+ if (!endpoint) {
843
+ return false;
844
+ }
845
+ this.endpoint = endpoint;
846
+ }
847
+ }
848
+ return true;
849
+ }
850
+ /**
851
+ *
852
+ * @private
853
+ */
854
+ _createSession(callback) {
855
+ (0, node_opcua_assert_1.assert)(typeof callback === "function");
856
+ (0, node_opcua_assert_1.assert)(this._secureChannel);
857
+ if (!this.__resolveEndPoint() || !this.endpoint) {
858
+ /* istanbul ignore next */
859
+ if (doDebug && this._serverEndpoints) {
860
+ debugLog(this._serverEndpoints.map((endpoint) => endpoint.endpointUrl + " " + endpoint.securityMode.toString() + " " + endpoint.securityPolicyUri));
861
+ }
862
+ return callback(new Error(" End point must exist " + this._secureChannel.endpointUrl));
863
+ }
864
+ this.serverUri = this.endpoint.server.applicationUri || "invalid application uri";
865
+ this.endpointUrl = this._secureChannel.endpointUrl;
866
+ const session = new client_session_impl_1.ClientSessionImpl(this);
867
+ this.__createSession_step2(session, callback);
868
+ }
869
+ /**
870
+ *
871
+ * @private
872
+ */
873
+ computeClientSignature(channel, serverCertificate, serverNonce) {
874
+ return (0, node_opcua_secure_channel_1.computeSignature)(serverCertificate, serverNonce || Buffer.alloc(0), this.getPrivateKey(), channel.securityPolicy);
875
+ }
876
+ /**
877
+ *
878
+ * @private
879
+ */
880
+ createUserIdentityToken(context, userIdentityInfo, callback) {
881
+ function coerceUserIdentityInfo(identityInfo) {
882
+ if (!identityInfo) {
883
+ return { type: node_opcua_service_endpoints_1.UserTokenType.Anonymous };
884
+ }
885
+ if (Object.prototype.hasOwnProperty.call(identityInfo, "type")) {
886
+ return identityInfo;
887
+ }
888
+ if (Object.prototype.hasOwnProperty.call(identityInfo, "userName")) {
889
+ identityInfo.type = node_opcua_service_endpoints_1.UserTokenType.UserName;
890
+ return identityInfo;
891
+ }
892
+ if (Object.prototype.hasOwnProperty.call(identityInfo, "certificateData")) {
893
+ identityInfo.type = node_opcua_service_endpoints_1.UserTokenType.Certificate;
894
+ return identityInfo;
895
+ }
896
+ identityInfo.type = node_opcua_service_endpoints_1.UserTokenType.Anonymous;
897
+ return identityInfo;
898
+ }
899
+ userIdentityInfo = coerceUserIdentityInfo(userIdentityInfo);
900
+ (0, node_opcua_assert_1.assert)(typeof callback === "function");
901
+ if (null === userIdentityInfo) {
902
+ return callback(null, {
903
+ userIdentityToken: null,
904
+ userTokenSignature: {}
905
+ });
906
+ }
907
+ let userIdentityToken;
908
+ let userTokenSignature = {
909
+ algorithm: undefined,
910
+ signature: undefined
911
+ };
912
+ try {
913
+ switch (userIdentityInfo.type) {
914
+ case node_opcua_service_endpoints_1.UserTokenType.Anonymous:
915
+ userIdentityToken = createAnonymousIdentityToken(context);
916
+ break;
917
+ case node_opcua_service_endpoints_1.UserTokenType.UserName: {
918
+ const userName = userIdentityInfo.userName || "";
919
+ const password = userIdentityInfo.password || "";
920
+ userIdentityToken = createUserNameIdentityToken(context, userName, password);
921
+ break;
922
+ }
923
+ case node_opcua_service_endpoints_1.UserTokenType.Certificate: {
924
+ const certificate = userIdentityInfo.certificateData;
925
+ const privateKey = userIdentityInfo.privateKey;
926
+ ({ userIdentityToken, userTokenSignature } = createX509IdentityToken(context, certificate, privateKey));
927
+ break;
928
+ }
929
+ default:
930
+ debugLog(" userIdentityInfo = ", userIdentityInfo);
931
+ return callback(new Error("CLIENT: Invalid userIdentityInfo"));
932
+ }
933
+ }
934
+ catch (err) {
935
+ if (typeof err === "string") {
936
+ return callback(new Error("Create identity token failed " + userIdentityInfo.type + " " + err));
937
+ }
938
+ return callback(err);
939
+ }
940
+ return callback(null, { userIdentityToken, userTokenSignature });
941
+ }
942
+ }
943
+ exports.OPCUAClientImpl = OPCUAClientImpl;
944
+ OPCUAClientImpl.minimumRevisedSessionTimeout = 100.0;
945
+ // tslint:disable:no-var-requires
946
+ // tslint:disable:max-line-length
947
+ const thenify = require("thenify");
948
+ /**
949
+ * @method createSession
950
+ * @async
951
+ *
952
+ * @example
953
+ * // create a anonymous session
954
+ * const session = await client.createSession();
955
+ *
956
+ * @example
957
+ * // create a session with a userName and password
958
+ * const userIdentityInfo = {
959
+ * type: UserTokenType.UserName,
960
+ * userName: "JoeDoe",
961
+ * password:"secret"
962
+ * };
963
+ * const session = client.createSession(userIdentityInfo);
964
+ *
965
+ */
966
+ OPCUAClientImpl.prototype.createSession = thenify.withCallback(OPCUAClientImpl.prototype.createSession);
967
+ OPCUAClientImpl.prototype.createSession2 = thenify.withCallback(OPCUAClientImpl.prototype.createSession2);
968
+ /**
969
+ * @method changeSessionIdentity
970
+ * @async
971
+ */
972
+ OPCUAClientImpl.prototype.changeSessionIdentity = thenify.withCallback(OPCUAClientImpl.prototype.changeSessionIdentity);
973
+ /**
974
+ * @method closeSession
975
+ * @async
976
+ * @example
977
+ * const session = await client.createSession();
978
+ * await client.closeSession(session);
979
+ */
980
+ OPCUAClientImpl.prototype.closeSession = thenify.withCallback(OPCUAClientImpl.prototype.closeSession);
981
+ OPCUAClientImpl.prototype.reactivateSession = thenify.withCallback(OPCUAClientImpl.prototype.reactivateSession);
982
982
  //# sourceMappingURL=opcua_client_impl.js.map