node-opcua-client 2.98.0 → 2.98.2

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