node-opcua-server 2.76.0 → 2.77.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 (63) hide show
  1. package/dist/base_server.d.ts +110 -110
  2. package/dist/base_server.js +473 -473
  3. package/dist/factory.d.ts +12 -12
  4. package/dist/factory.js +23 -23
  5. package/dist/factory.js.map +1 -1
  6. package/dist/filter/check_where_clause_on_address_space.d.ts +3 -3
  7. package/dist/filter/check_where_clause_on_address_space.js +22 -22
  8. package/dist/filter/extract_event_fields.d.ts +10 -10
  9. package/dist/filter/extract_event_fields.js +17 -17
  10. package/dist/helper.d.ts +10 -10
  11. package/dist/helper.js +75 -75
  12. package/dist/history_server_capabilities.d.ts +35 -35
  13. package/dist/history_server_capabilities.js +43 -43
  14. package/dist/i_channel_data.d.ts +13 -13
  15. package/dist/i_channel_data.js +2 -2
  16. package/dist/i_register_server_manager.d.ts +16 -16
  17. package/dist/i_register_server_manager.js +2 -2
  18. package/dist/i_server_side_publish_engine.d.ts +36 -36
  19. package/dist/i_server_side_publish_engine.js +49 -49
  20. package/dist/i_socket_data.d.ts +11 -11
  21. package/dist/i_socket_data.js +2 -2
  22. package/dist/index.d.ts +16 -16
  23. package/dist/index.js +32 -32
  24. package/dist/monitored_item.d.ts +177 -177
  25. package/dist/monitored_item.js +1001 -1001
  26. package/dist/node_sampler.d.ts +3 -3
  27. package/dist/node_sampler.js +75 -75
  28. package/dist/opcua_server.d.ts +747 -747
  29. package/dist/opcua_server.js +2431 -2431
  30. package/dist/queue.d.ts +11 -11
  31. package/dist/queue.js +71 -71
  32. package/dist/register_server_manager.d.ts +96 -96
  33. package/dist/register_server_manager.js +584 -584
  34. package/dist/register_server_manager_hidden.d.ts +17 -17
  35. package/dist/register_server_manager_hidden.js +27 -27
  36. package/dist/register_server_manager_mdns_only.d.ts +22 -22
  37. package/dist/register_server_manager_mdns_only.js +55 -55
  38. package/dist/server_capabilities.d.ts +148 -148
  39. package/dist/server_capabilities.js +92 -92
  40. package/dist/server_end_point.d.ts +183 -183
  41. package/dist/server_end_point.js +819 -817
  42. package/dist/server_end_point.js.map +1 -1
  43. package/dist/server_engine.d.ts +317 -317
  44. package/dist/server_engine.js +1716 -1716
  45. package/dist/server_publish_engine.d.ts +113 -113
  46. package/dist/server_publish_engine.js +541 -541
  47. package/dist/server_publish_engine_for_orphan_subscriptions.d.ts +16 -16
  48. package/dist/server_publish_engine_for_orphan_subscriptions.js +51 -51
  49. package/dist/server_session.d.ts +182 -182
  50. package/dist/server_session.js +739 -739
  51. package/dist/server_subscription.d.ts +421 -421
  52. package/dist/server_subscription.js +1346 -1346
  53. package/dist/sessions_compatible_for_transfer.d.ts +2 -2
  54. package/dist/sessions_compatible_for_transfer.js +39 -39
  55. package/dist/user_manager.d.ts +32 -32
  56. package/dist/user_manager.js +74 -74
  57. package/dist/user_manager_ua.d.ts +3 -3
  58. package/dist/user_manager_ua.js +39 -39
  59. package/dist/validate_filter.d.ts +5 -5
  60. package/dist/validate_filter.js +60 -60
  61. package/package.json +48 -47
  62. package/source/factory.ts +2 -2
  63. package/source/server_end_point.ts +1 -0
@@ -1,2432 +1,2432 @@
1
- "use strict";
2
- /* eslint-disable complexity */
3
- /**
4
- * @module node-opcua-server
5
- */
6
- // tslint:disable:no-console
7
- // tslint:disable:max-line-length
8
- // tslint:disable:unified-signatures
9
- var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
10
- function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
11
- return new (P || (P = Promise))(function (resolve, reject) {
12
- function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
13
- function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
14
- function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
15
- step((generator = generator.apply(thisArg, _arguments || [])).next());
16
- });
17
- };
18
- Object.defineProperty(exports, "__esModule", { value: true });
19
- exports.OPCUAServer = exports.RegisterServerMethod = exports.filterDiagnosticInfo = void 0;
20
- const crypto = require("crypto");
21
- const util_1 = require("util");
22
- const async = require("async");
23
- const chalk = require("chalk");
24
- const node_opcua_hostname_1 = require("node-opcua-hostname");
25
- const node_opcua_assert_1 = require("node-opcua-assert");
26
- const utils = require("node-opcua-utils");
27
- const node_opcua_address_space_1 = require("node-opcua-address-space");
28
- const node_opcua_certificate_manager_1 = require("node-opcua-certificate-manager");
29
- const node_opcua_common_1 = require("node-opcua-common");
30
- const node_opcua_crypto_1 = require("node-opcua-crypto");
31
- const node_opcua_data_model_1 = require("node-opcua-data-model");
32
- const node_opcua_data_value_1 = require("node-opcua-data-value");
33
- const node_opcua_debug_1 = require("node-opcua-debug");
34
- const node_opcua_object_registry_1 = require("node-opcua-object-registry");
35
- const node_opcua_secure_channel_1 = require("node-opcua-secure-channel");
36
- const node_opcua_service_browse_1 = require("node-opcua-service-browse");
37
- const node_opcua_service_call_1 = require("node-opcua-service-call");
38
- const node_opcua_service_endpoints_1 = require("node-opcua-service-endpoints");
39
- const node_opcua_service_history_1 = require("node-opcua-service-history");
40
- const node_opcua_service_node_management_1 = require("node-opcua-service-node-management");
41
- const node_opcua_service_query_1 = require("node-opcua-service-query");
42
- const node_opcua_service_read_1 = require("node-opcua-service-read");
43
- const node_opcua_service_register_node_1 = require("node-opcua-service-register-node");
44
- const node_opcua_service_session_1 = require("node-opcua-service-session");
45
- const node_opcua_service_subscription_1 = require("node-opcua-service-subscription");
46
- const node_opcua_service_translate_browse_path_1 = require("node-opcua-service-translate-browse-path");
47
- const node_opcua_service_write_1 = require("node-opcua-service-write");
48
- const node_opcua_status_code_1 = require("node-opcua-status-code");
49
- const node_opcua_types_1 = require("node-opcua-types");
50
- const node_opcua_variant_1 = require("node-opcua-variant");
51
- const node_opcua_variant_2 = require("node-opcua-variant");
52
- const node_opcua_utils_1 = require("node-opcua-utils");
53
- const base_server_1 = require("./base_server");
54
- const factory_1 = require("./factory");
55
- const monitored_item_1 = require("./monitored_item");
56
- const register_server_manager_1 = require("./register_server_manager");
57
- const register_server_manager_hidden_1 = require("./register_server_manager_hidden");
58
- const register_server_manager_mdns_only_1 = require("./register_server_manager_mdns_only");
59
- const server_end_point_1 = require("./server_end_point");
60
- const server_engine_1 = require("./server_engine");
61
- const user_manager_1 = require("./user_manager");
62
- const user_manager_ua_1 = require("./user_manager_ua");
63
- function isSubscriptionIdInvalid(subscriptionId) {
64
- return subscriptionId < 0 || subscriptionId >= 0xffffffff;
65
- }
66
- // tslint:disable-next-line:no-var-requires
67
- const thenify = require("thenify");
68
- // tslint:disable-next-line:no-var-requires
69
- const package_info = require("../package.json");
70
- const debugLog = (0, node_opcua_debug_1.make_debugLog)(__filename);
71
- const errorLog = (0, node_opcua_debug_1.make_errorLog)(__filename);
72
- const warningLog = (0, node_opcua_debug_1.make_warningLog)(__filename);
73
- const default_maxConnectionsPerEndpoint = 10;
74
- function g_sendError(channel, message, ResponseClass, statusCode) {
75
- const response = new node_opcua_types_1.ServiceFault({
76
- responseHeader: { serviceResult: statusCode }
77
- });
78
- return channel.send_response("MSG", response, message);
79
- }
80
- const default_build_info = {
81
- manufacturerName: "NodeOPCUA : MIT Licence ( see http://node-opcua.github.io/)",
82
- productName: "NodeOPCUA-Server",
83
- productUri: null,
84
- softwareVersion: package_info.version,
85
- buildNumber: "0",
86
- buildDate: new Date(2020, 1, 1)
87
- // xx buildDate: fs.statSync(package_json_file).mtime
88
- };
89
- const minSessionTimeout = 100; // 100 milliseconds
90
- const defaultSessionTimeout = 1000 * 30; // 30 seconds
91
- const maxSessionTimeout = 1000 * 60 * 50; // 50 minutes
92
- let unnamed_session_count = 0;
93
- function _adjust_session_timeout(sessionTimeout) {
94
- let revisedSessionTimeout = sessionTimeout || defaultSessionTimeout;
95
- revisedSessionTimeout = Math.min(revisedSessionTimeout, maxSessionTimeout);
96
- revisedSessionTimeout = Math.max(revisedSessionTimeout, minSessionTimeout);
97
- return revisedSessionTimeout;
98
- }
99
- function channel_has_session(channel, session) {
100
- if (session.channel === channel) {
101
- (0, node_opcua_assert_1.assert)(Object.prototype.hasOwnProperty.call(channel.sessionTokens, session.authenticationToken.toString()));
102
- return true;
103
- }
104
- return false;
105
- }
106
- function moveSessionToChannel(session, channel) {
107
- debugLog("moveSessionToChannel sessionId", session.nodeId, " channelId=", channel.channelId);
108
- if (session.publishEngine) {
109
- session.publishEngine.cancelPendingPublishRequestBeforeChannelChange();
110
- }
111
- session._detach_channel();
112
- session._attach_channel(channel);
113
- (0, node_opcua_assert_1.assert)(session.channel.channelId === channel.channelId);
114
- }
115
- function _attempt_to_close_some_old_unactivated_session(server) {
116
- return __awaiter(this, void 0, void 0, function* () {
117
- const session = server.engine.getOldestInactiveSession();
118
- if (session) {
119
- yield server.engine.closeSession(session.authenticationToken, false, "Forcing");
120
- }
121
- });
122
- }
123
- function getRequiredEndpointInfo(endpoint) {
124
- (0, node_opcua_assert_1.assert)(endpoint instanceof node_opcua_types_1.EndpointDescription);
125
- // https://reference.opcfoundation.org/v104/Core/docs/Part4/5.6.2/
126
- // https://reference.opcfoundation.org/v105/Core/docs/Part4/5.6.2/
127
- const e = new node_opcua_types_1.EndpointDescription({
128
- endpointUrl: endpoint.endpointUrl,
129
- securityLevel: endpoint.securityLevel,
130
- securityMode: endpoint.securityMode,
131
- securityPolicyUri: endpoint.securityPolicyUri,
132
- server: {
133
- applicationUri: endpoint.server.applicationUri,
134
- applicationType: endpoint.server.applicationType,
135
- applicationName: endpoint.server.applicationName,
136
- productUri: endpoint.server.productUri
137
- },
138
- transportProfileUri: endpoint.transportProfileUri,
139
- userIdentityTokens: endpoint.userIdentityTokens
140
- });
141
- // reduce even further by explicitly setting unwanted members to null
142
- e.server.applicationName = null;
143
- // xx e.server.applicationType = null as any;
144
- e.server.gatewayServerUri = null;
145
- e.server.discoveryProfileUri = null;
146
- e.server.discoveryUrls = null;
147
- e.serverCertificate = null;
148
- return e;
149
- }
150
- // serverUri String This value is only specified if the EndpointDescription has a gatewayServerUri.
151
- // This value is the applicationUri from the EndpointDescription which is the applicationUri for the
152
- // underlying Server. The type EndpointDescription is defined in 7.10.
153
- function _serverEndpointsForCreateSessionResponse(server, endpointUrl, serverUri) {
154
- serverUri = null; // unused then
155
- // https://reference.opcfoundation.org/v104/Core/docs/Part4/5.6.2/
156
- // https://reference.opcfoundation.org/v105/Core/docs/Part4/5.6.2/
157
- return server
158
- ._get_endpoints(endpointUrl)
159
- .filter((e) => !e.restricted) // remove restricted endpoints
160
- .filter((e) => (0, node_opcua_utils_1.matchUri)(e.endpointUrl, endpointUrl))
161
- .map(getRequiredEndpointInfo);
162
- }
163
- function adjustSecurityPolicy(channel, userTokenPolicy_securityPolicyUri) {
164
- // check that userIdentityToken
165
- let securityPolicy = (0, node_opcua_secure_channel_1.fromURI)(userTokenPolicy_securityPolicyUri);
166
- // if the security policy is not specified we use the session security policy
167
- if (securityPolicy === node_opcua_secure_channel_1.SecurityPolicy.Invalid) {
168
- securityPolicy = (0, node_opcua_secure_channel_1.fromURI)(channel.clientSecurityHeader.securityPolicyUri);
169
- (0, node_opcua_assert_1.assert)(securityPolicy !== node_opcua_secure_channel_1.SecurityPolicy.Invalid);
170
- }
171
- return securityPolicy;
172
- }
173
- function findUserTokenByPolicy(endpoint_description, userTokenType, policyId) {
174
- (0, node_opcua_assert_1.assert)(endpoint_description instanceof node_opcua_types_1.EndpointDescription);
175
- const r = endpoint_description.userIdentityTokens.filter((userIdentity) => userIdentity.tokenType === userTokenType && (!policyId || userIdentity.policyId === policyId));
176
- return r.length === 0 ? null : r[0];
177
- }
178
- function findUserTokenPolicy(endpoint_description, userTokenType) {
179
- (0, node_opcua_assert_1.assert)(endpoint_description instanceof node_opcua_types_1.EndpointDescription);
180
- const r = endpoint_description.userIdentityTokens.filter((userIdentity) => {
181
- (0, node_opcua_assert_1.assert)(userIdentity.tokenType !== undefined);
182
- return userIdentity.tokenType === userTokenType;
183
- });
184
- return r.length === 0 ? null : r[0];
185
- }
186
- function createAnonymousIdentityToken(endpoint_desc) {
187
- (0, node_opcua_assert_1.assert)(endpoint_desc instanceof node_opcua_types_1.EndpointDescription);
188
- const userTokenPolicy = findUserTokenPolicy(endpoint_desc, node_opcua_service_endpoints_1.UserTokenType.Anonymous);
189
- if (!userTokenPolicy) {
190
- throw new Error("Cannot find ANONYMOUS user token policy in end point description");
191
- }
192
- return new node_opcua_service_session_1.AnonymousIdentityToken({ policyId: userTokenPolicy.policyId });
193
- }
194
- function sameIdentityToken(token1, token2) {
195
- if (token1 instanceof node_opcua_service_session_1.UserNameIdentityToken) {
196
- if (!(token2 instanceof node_opcua_service_session_1.UserNameIdentityToken)) {
197
- return false;
198
- }
199
- if (token1.userName !== token2.userName) {
200
- return false;
201
- }
202
- if (token1.password.toString("hex") !== token2.password.toString("hex")) {
203
- return false;
204
- }
205
- }
206
- else if (token1 instanceof node_opcua_service_session_1.AnonymousIdentityToken) {
207
- if (!(token2 instanceof node_opcua_service_session_1.AnonymousIdentityToken)) {
208
- return false;
209
- }
210
- if (token1.policyId !== token2.policyId) {
211
- return false;
212
- }
213
- return true;
214
- }
215
- (0, node_opcua_assert_1.assert)(false, " Not implemented yet");
216
- return false;
217
- }
218
- function getTokenType(userIdentityToken) {
219
- if (userIdentityToken instanceof node_opcua_service_session_1.AnonymousIdentityToken) {
220
- return node_opcua_service_endpoints_1.UserTokenType.Anonymous;
221
- }
222
- else if (userIdentityToken instanceof node_opcua_service_session_1.UserNameIdentityToken) {
223
- return node_opcua_service_endpoints_1.UserTokenType.UserName;
224
- }
225
- else if (userIdentityToken instanceof node_opcua_types_1.IssuedIdentityToken) {
226
- return node_opcua_service_endpoints_1.UserTokenType.IssuedToken;
227
- }
228
- else if (userIdentityToken instanceof node_opcua_service_session_1.X509IdentityToken) {
229
- return node_opcua_service_endpoints_1.UserTokenType.Certificate;
230
- }
231
- return node_opcua_service_endpoints_1.UserTokenType.Invalid;
232
- }
233
- function thumbprint(certificate) {
234
- return certificate ? certificate.toString("base64") : "";
235
- }
236
- /*=== private
237
- *
238
- * perform the read operation on a given node for a monitored item.
239
- * this method DOES NOT apply to Variable Values attribute
240
- *
241
- * @param self
242
- * @param oldValue
243
- * @param node
244
- * @param itemToMonitor
245
- * @private
246
- */
247
- function monitoredItem_read_and_record_value(self, context, oldValue, node, itemToMonitor, callback) {
248
- (0, node_opcua_assert_1.assert)(self instanceof monitored_item_1.MonitoredItem);
249
- (0, node_opcua_assert_1.assert)(oldValue instanceof node_opcua_data_value_1.DataValue);
250
- (0, node_opcua_assert_1.assert)(itemToMonitor.attributeId === node_opcua_data_model_1.AttributeIds.Value);
251
- const dataValue = node.readAttribute(context, itemToMonitor.attributeId, itemToMonitor.indexRange, itemToMonitor.dataEncoding);
252
- callback(null, dataValue);
253
- }
254
- /*== private
255
- * @method monitoredItem_read_and_record_value_async
256
- * this method applies to Variable Values attribute
257
- * @param self
258
- * @param oldValue
259
- * @param node
260
- * @param itemToMonitor
261
- * @private
262
- */
263
- function monitoredItem_read_and_record_value_async(self, context, oldValue, node, itemToMonitor, callback) {
264
- (0, node_opcua_assert_1.assert)(context instanceof node_opcua_address_space_1.SessionContext);
265
- (0, node_opcua_assert_1.assert)(itemToMonitor.attributeId === node_opcua_data_model_1.AttributeIds.Value);
266
- (0, node_opcua_assert_1.assert)(self instanceof monitored_item_1.MonitoredItem);
267
- (0, node_opcua_assert_1.assert)(oldValue instanceof node_opcua_data_value_1.DataValue);
268
- // do it asynchronously ( this is only valid for value attributes )
269
- (0, node_opcua_assert_1.assert)(itemToMonitor.attributeId === node_opcua_data_model_1.AttributeIds.Value);
270
- node.readValueAsync(context, (err, dataValue) => {
271
- callback(err, dataValue);
272
- });
273
- }
274
- function build_scanning_node_function(context, addressSpace, monitoredItem, itemToMonitor) {
275
- (0, node_opcua_assert_1.assert)(context instanceof node_opcua_address_space_1.SessionContext);
276
- (0, node_opcua_assert_1.assert)(itemToMonitor instanceof node_opcua_service_read_1.ReadValueId);
277
- const node = addressSpace.findNode(itemToMonitor.nodeId);
278
- /* istanbul ignore next */
279
- if (!node) {
280
- errorLog(" INVALID NODE ID , ", itemToMonitor.nodeId.toString());
281
- (0, node_opcua_debug_1.dump)(itemToMonitor);
282
- return (oldData, callback) => {
283
- callback(null, new node_opcua_data_value_1.DataValue({
284
- statusCode: node_opcua_status_code_1.StatusCodes.BadNodeIdUnknown,
285
- value: { dataType: node_opcua_variant_1.DataType.Null, value: 0 }
286
- }));
287
- };
288
- }
289
- ///// !!monitoredItem.setNode(node);
290
- if (itemToMonitor.attributeId === node_opcua_data_model_1.AttributeIds.Value) {
291
- const monitoredItem_read_and_record_value_func = itemToMonitor.attributeId === node_opcua_data_model_1.AttributeIds.Value && typeof node.readValueAsync === "function"
292
- ? monitoredItem_read_and_record_value_async
293
- : monitoredItem_read_and_record_value;
294
- return function func(oldDataValue, callback) {
295
- (0, node_opcua_assert_1.assert)(this instanceof monitored_item_1.MonitoredItem);
296
- (0, node_opcua_assert_1.assert)(oldDataValue instanceof node_opcua_data_value_1.DataValue);
297
- (0, node_opcua_assert_1.assert)(typeof callback === "function");
298
- monitoredItem_read_and_record_value_func(this, context, oldDataValue, node, itemToMonitor, callback);
299
- };
300
- }
301
- else {
302
- // Attributes, other than the Value Attribute, are only monitored for a change in value.
303
- // The filter is not used for these Attributes. Any change in value for these Attributes
304
- // causes a Notification to be generated.
305
- // only record value when it has changed
306
- return function func(oldDataValue, callback) {
307
- (0, node_opcua_assert_1.assert)(this instanceof monitored_item_1.MonitoredItem);
308
- (0, node_opcua_assert_1.assert)(oldDataValue instanceof node_opcua_data_value_1.DataValue);
309
- (0, node_opcua_assert_1.assert)(typeof callback === "function");
310
- const newDataValue = node.readAttribute(null, itemToMonitor.attributeId);
311
- callback(null, newDataValue);
312
- };
313
- }
314
- }
315
- function prepareMonitoredItem(context, addressSpace, monitoredItem) {
316
- const itemToMonitor = monitoredItem.itemToMonitor;
317
- const readNodeFunc = build_scanning_node_function(context, addressSpace, monitoredItem, itemToMonitor);
318
- monitoredItem.samplingFunc = readNodeFunc;
319
- }
320
- function isMonitoringModeValid(monitoringMode) {
321
- (0, node_opcua_assert_1.assert)(node_opcua_types_1.MonitoringMode.Invalid !== undefined);
322
- return monitoringMode !== node_opcua_types_1.MonitoringMode.Invalid && monitoringMode <= node_opcua_types_1.MonitoringMode.Reporting;
323
- }
324
- function _installRegisterServerManager(self) {
325
- (0, node_opcua_assert_1.assert)(self instanceof OPCUAServer);
326
- (0, node_opcua_assert_1.assert)(!self.registerServerManager);
327
- /* istanbul ignore next */
328
- if (!self.registerServerMethod) {
329
- throw new Error("Internal Error");
330
- }
331
- switch (self.registerServerMethod) {
332
- case RegisterServerMethod.HIDDEN:
333
- self.registerServerManager = new register_server_manager_hidden_1.RegisterServerManagerHidden({
334
- server: self
335
- });
336
- break;
337
- case RegisterServerMethod.MDNS:
338
- self.registerServerManager = new register_server_manager_mdns_only_1.RegisterServerManagerMDNSONLY({
339
- server: self
340
- });
341
- break;
342
- case RegisterServerMethod.LDS:
343
- self.registerServerManager = new register_server_manager_1.RegisterServerManager({
344
- discoveryServerEndpointUrl: self.discoveryServerEndpointUrl,
345
- server: self
346
- });
347
- break;
348
- /* istanbul ignore next */
349
- default:
350
- throw new Error("Invalid switch");
351
- }
352
- self.registerServerManager.on("serverRegistrationPending", () => {
353
- /**
354
- * emitted when the server is trying to registered the LDS
355
- * but when the connection to the lds has failed
356
- * serverRegistrationPending is sent when the backoff signal of the
357
- * connection process is raised
358
- * @event serverRegistrationPending
359
- */
360
- debugLog("serverRegistrationPending");
361
- self.emit("serverRegistrationPending");
362
- });
363
- self.registerServerManager.on("serverRegistered", () => {
364
- /**
365
- * emitted when the server is successfully registered to the LDS
366
- * @event serverRegistered
367
- */
368
- debugLog("serverRegistered");
369
- self.emit("serverRegistered");
370
- });
371
- self.registerServerManager.on("serverRegistrationRenewed", () => {
372
- /**
373
- * emitted when the server has successfully renewed its registration to the LDS
374
- * @event serverRegistrationRenewed
375
- */
376
- debugLog("serverRegistrationRenewed");
377
- self.emit("serverRegistrationRenewed");
378
- });
379
- self.registerServerManager.on("serverUnregistered", () => {
380
- debugLog("serverUnregistered");
381
- /**
382
- * emitted when the server is successfully unregistered to the LDS
383
- * ( for instance during shutdown)
384
- * @event serverUnregistered
385
- */
386
- self.emit("serverUnregistered");
387
- });
388
- }
389
- function validate_applicationUri(channel, request) {
390
- var _a, _b;
391
- const applicationUri = request.clientDescription.applicationUri;
392
- const clientCertificate = request.clientCertificate;
393
- // if session is insecure there is no need to check certificate information
394
- if (channel.securityMode === node_opcua_secure_channel_1.MessageSecurityMode.None) {
395
- return true; // assume correct
396
- }
397
- if (!clientCertificate || clientCertificate.length === 0) {
398
- return true; // can't check
399
- }
400
- const e = (0, node_opcua_crypto_1.exploreCertificate)(clientCertificate);
401
- const uniformResourceIdentifier = (_b = (_a = e.tbsCertificate.extensions.subjectAltName) === null || _a === void 0 ? void 0 : _a.uniformResourceIdentifier) !== null && _b !== void 0 ? _b : null;
402
- const applicationUriFromCert = uniformResourceIdentifier && uniformResourceIdentifier.length > 0 ? uniformResourceIdentifier[0] : null;
403
- /* istanbul ignore next */
404
- if (applicationUriFromCert !== applicationUri) {
405
- errorLog("BadCertificateUriInvalid!");
406
- errorLog("applicationUri = ", applicationUri);
407
- errorLog("applicationUriFromCert = ", applicationUriFromCert);
408
- }
409
- return applicationUriFromCert === applicationUri;
410
- }
411
- function validate_security_endpoint(server, request, channel) {
412
- debugLog("validate_security_endpoint = ", request.endpointUrl);
413
- let endpoints = server._get_endpoints(request.endpointUrl);
414
- // endpointUrl String The network address that the Client used to access the Session Endpoint.
415
- // The HostName portion of the URL should be one of the HostNames for the application that are
416
- // specified in the Server’s ApplicationInstanceCertificate (see 7.2). The Server shall raise an
417
- // AuditUrlMismatchEventType event if the URL does not match the Server’s HostNames.
418
- // AuditUrlMismatchEventType event type is defined in Part 5.
419
- // The Server uses this information for diagnostics and to determine the set of
420
- // EndpointDescriptions to return in the response.
421
- // ToDo: check endpointUrl validity and emit an AuditUrlMismatchEventType event if not
422
- if (endpoints.length === 0) {
423
- // we have a UrlMismatch here
424
- const ua_server = server.engine.addressSpace.rootFolder.objects.server;
425
- ua_server.raiseEvent("AuditUrlMismatchEventType", {
426
- endpointUrl: { dataType: node_opcua_variant_1.DataType.String, value: request.endpointUrl }
427
- });
428
- debugLog("Cannot find endpoint in available endpoints with endpointUri", request.endpointUrl);
429
- if (OPCUAServer.requestExactEndpointUrl) {
430
- return { errCode: node_opcua_status_code_1.StatusCodes.BadServiceUnsupported };
431
- }
432
- else {
433
- endpoints = server._get_endpoints(null);
434
- }
435
- }
436
- // ignore restricted endpoints
437
- endpoints = endpoints.filter((e) => !e.restricted);
438
- const endpoints_matching_security_mode = endpoints.filter((e) => {
439
- return e.securityMode === channel.securityMode;
440
- });
441
- if (endpoints_matching_security_mode.length === 0) {
442
- return { errCode: node_opcua_status_code_1.StatusCodes.BadSecurityModeRejected };
443
- }
444
- const endpoints_matching_security_policy = endpoints_matching_security_mode.filter((e) => {
445
- return e.securityPolicyUri === channel.securityHeader.securityPolicyUri;
446
- });
447
- if (endpoints_matching_security_policy.length === 0) {
448
- return { errCode: node_opcua_status_code_1.StatusCodes.BadSecurityPolicyRejected };
449
- }
450
- if (endpoints_matching_security_policy.length !== 1) {
451
- debugLog("endpoints_matching_security_policy= ", endpoints_matching_security_policy.length);
452
- }
453
- return { errCode: node_opcua_status_code_1.StatusCodes.Good, endpoint: endpoints_matching_security_policy[0] };
454
- }
455
- function filterDiagnosticInfo(returnDiagnostics, response) {
456
- if (node_opcua_data_model_1.RESPONSE_DIAGNOSTICS_MASK_ALL & returnDiagnostics) {
457
- response.responseHeader.serviceDiagnostics = (0, node_opcua_data_model_1.filterDiagnosticServiceLevel)(returnDiagnostics, response.responseHeader.serviceDiagnostics);
458
- if (response.diagnosticInfos && response.diagnosticInfos.length > 0) {
459
- response.diagnosticInfos = response.diagnosticInfos.map((d) => (0, node_opcua_data_model_1.filterDiagnosticOperationLevel)(returnDiagnostics, d));
460
- }
461
- else {
462
- response.diagnosticInfos = [];
463
- }
464
- if (response.results) {
465
- for (const entry of response.results) {
466
- if (entry.inputArgumentDiagnosticInfos && entry.inputArgumentDiagnosticInfos.length > 0) {
467
- entry.inputArgumentDiagnosticInfos = entry.inputArgumentDiagnosticInfos.map((d) => (0, node_opcua_data_model_1.filterDiagnosticOperationLevel)(returnDiagnostics, d));
468
- }
469
- else {
470
- entry.inputArgumentDiagnosticInfos = [];
471
- }
472
- }
473
- }
474
- }
475
- }
476
- exports.filterDiagnosticInfo = filterDiagnosticInfo;
477
- var RegisterServerMethod;
478
- (function (RegisterServerMethod) {
479
- RegisterServerMethod[RegisterServerMethod["HIDDEN"] = 1] = "HIDDEN";
480
- RegisterServerMethod[RegisterServerMethod["MDNS"] = 2] = "MDNS";
481
- RegisterServerMethod[RegisterServerMethod["LDS"] = 3] = "LDS"; // the server registers itself to the LDS or LDS-ME (Local Discovery Server)
482
- })(RegisterServerMethod = exports.RegisterServerMethod || (exports.RegisterServerMethod = {}));
483
- const g_requestExactEndpointUrl = !!process.env.NODEOPCUA_SERVER_REQUEST_EXACT_ENDPOINT_URL;
484
- /**
485
- *
486
- */
487
- class OPCUAServer extends base_server_1.OPCUABaseServer {
488
- constructor(options) {
489
- super(options);
490
- /**
491
- * false if anonymous connection are not allowed
492
- */
493
- this.allowAnonymous = false;
494
- this.allowAnonymous = false;
495
- options = options || {};
496
- this.options = options;
497
- if (options.maxAllowedSessionNumber !== undefined) {
498
- warningLog("[NODE-OPCUA-W21] maxAllowedSessionNumber property is now deprecated , please use serverCapabilities.maxSessions instead");
499
- options.serverCapabilities = options.serverCapabilities || {};
500
- options.serverCapabilities.maxSessions = options.maxAllowedSessionNumber;
501
- }
502
- /**
503
- * @property maxConnectionsPerEndpoint
504
- */
505
- this.maxConnectionsPerEndpoint = options.maxConnectionsPerEndpoint || default_maxConnectionsPerEndpoint;
506
- // build Info
507
- const buildInfo = Object.assign(Object.assign({}, default_build_info), options.buildInfo);
508
- // repair product name
509
- buildInfo.productUri = buildInfo.productUri || this.serverInfo.productUri;
510
- this.serverInfo.productUri = this.serverInfo.productUri || buildInfo.productUri;
511
- this.userManager = (0, user_manager_1.makeUserManager)(options.userManager);
512
- options.allowAnonymous = options.allowAnonymous === undefined ? true : !!options.allowAnonymous;
513
- /**
514
- * @property allowAnonymous
515
- */
516
- this.allowAnonymous = options.allowAnonymous;
517
- this.discoveryServerEndpointUrl = options.discoveryServerEndpointUrl || "opc.tcp://%FQDN%:4840";
518
- (0, node_opcua_assert_1.assert)(typeof this.discoveryServerEndpointUrl === "string");
519
- this.serverInfo.applicationType = node_opcua_service_endpoints_1.ApplicationType.Server;
520
- this.capabilitiesForMDNS = options.capabilitiesForMDNS || ["NA"];
521
- this.registerServerMethod = options.registerServerMethod || RegisterServerMethod.HIDDEN;
522
- _installRegisterServerManager(this);
523
- if (!options.userCertificateManager) {
524
- this.userCertificateManager = (0, node_opcua_certificate_manager_1.getDefaultCertificateManager)("UserPKI");
525
- }
526
- else {
527
- this.userCertificateManager = options.userCertificateManager;
528
- }
529
- // note: we need to delay initialization of endpoint as certain resources
530
- // such as %FQDN% might not be ready yet at this stage
531
- this._delayInit = () => __awaiter(this, void 0, void 0, function* () {
532
- /* istanbul ignore next */
533
- if (!options) {
534
- throw new Error("Internal Error");
535
- }
536
- // to check => this.serverInfo.applicationName = this.serverInfo.productName || buildInfo.productName;
537
- // note: applicationUri is handled in a special way
538
- this.engine = new server_engine_1.ServerEngine({
539
- applicationUri: () => this.serverInfo.applicationUri,
540
- buildInfo,
541
- isAuditing: options.isAuditing,
542
- serverCapabilities: options.serverCapabilities
543
- });
544
- this.objectFactory = new factory_1.Factory(this.engine);
545
- const endpointDefinitions = options.alternateEndpoints || [];
546
- const hostname = (0, node_opcua_hostname_1.getFullyQualifiedDomainName)();
547
- endpointDefinitions.push({
548
- port: options.port || 26543,
549
- allowAnonymous: options.allowAnonymous,
550
- alternateHostname: options.alternateHostname,
551
- disableDiscovery: options.disableDiscovery,
552
- hostname: options.hostname || hostname,
553
- securityModes: options.securityModes,
554
- securityPolicies: options.securityPolicies
555
- });
556
- // todo should self.serverInfo.productUri match self.engine.buildInfo.productUri ?
557
- for (const endpointOptions of endpointDefinitions) {
558
- const endPoint = this.createEndpointDescriptions(options, endpointOptions);
559
- this.endpoints.push(endPoint);
560
- endPoint.on("message", (message, channel) => {
561
- this.on_request(message, channel);
562
- });
563
- endPoint.on("error", (err) => {
564
- errorLog("OPCUAServer endpoint error", err);
565
- // set serverState to ServerState.Failed;
566
- this.engine.setServerState(node_opcua_common_1.ServerState.Failed);
567
- this.shutdown(() => {
568
- /* empty */
569
- });
570
- });
571
- }
572
- });
573
- }
574
- /**
575
- * total number of bytes written by the server since startup
576
- */
577
- get bytesWritten() {
578
- return this.endpoints.reduce((accumulated, endpoint) => {
579
- return accumulated + endpoint.bytesWritten;
580
- }, 0);
581
- }
582
- /**
583
- * total number of bytes read by the server since startup
584
- */
585
- get bytesRead() {
586
- return this.endpoints.reduce((accumulated, endpoint) => {
587
- return accumulated + endpoint.bytesRead;
588
- }, 0);
589
- }
590
- /**
591
- * Number of transactions processed by the server since startup
592
- */
593
- get transactionsCount() {
594
- return this.endpoints.reduce((accumulated, endpoint) => {
595
- return accumulated + endpoint.transactionsCount;
596
- }, 0);
597
- }
598
- /**
599
- * The server build info
600
- */
601
- get buildInfo() {
602
- return this.engine.buildInfo;
603
- }
604
- /**
605
- * the number of connected channel on all existing end points
606
- */
607
- get currentChannelCount() {
608
- // TODO : move to base
609
- return this.endpoints.reduce((currentValue, endPoint) => {
610
- return currentValue + endPoint.currentChannelCount;
611
- }, 0);
612
- }
613
- /**
614
- * The number of active subscriptions from all sessions
615
- */
616
- get currentSubscriptionCount() {
617
- return this.engine ? this.engine.currentSubscriptionCount : 0;
618
- }
619
- /**
620
- * the number of session activation requests that have been rejected
621
- */
622
- get rejectedSessionCount() {
623
- return this.engine ? this.engine.rejectedSessionCount : 0;
624
- }
625
- /**
626
- * the number of request that have been rejected
627
- */
628
- get rejectedRequestsCount() {
629
- return this.engine ? this.engine.rejectedRequestsCount : 0;
630
- }
631
- /**
632
- * the number of sessions that have been aborted
633
- */
634
- get sessionAbortCount() {
635
- return this.engine ? this.engine.sessionAbortCount : 0;
636
- }
637
- /**
638
- * the publishing interval count
639
- */
640
- get publishingIntervalCount() {
641
- return this.engine ? this.engine.publishingIntervalCount : 0;
642
- }
643
- /**
644
- * the number of sessions currently active
645
- */
646
- get currentSessionCount() {
647
- return this.engine ? this.engine.currentSessionCount : 0;
648
- }
649
- /**
650
- * true if the server has been initialized
651
- *
652
- */
653
- get initialized() {
654
- return this.engine && this.engine.addressSpace !== null;
655
- }
656
- /**
657
- * is the server auditing ?
658
- */
659
- get isAuditing() {
660
- return this.engine ? this.engine.isAuditing : false;
661
- }
662
- /**
663
- * the maximum number of concurrent sessions allowed on the server
664
- */
665
- get maxAllowedSessionNumber() {
666
- return this.engine.serverCapabilities.maxSessions;
667
- }
668
- initialize(...args) {
669
- const done = args[0];
670
- (0, node_opcua_assert_1.assert)(!this.initialized, "server is already initialized"); // already initialized ?
671
- this._preInitTask.push(() => __awaiter(this, void 0, void 0, function* () {
672
- /* istanbul ignore else */
673
- if (this._delayInit) {
674
- yield this._delayInit();
675
- this._delayInit = undefined;
676
- }
677
- }));
678
- this.performPreInitialization()
679
- .then(() => {
680
- OPCUAServer.registry.register(this);
681
- this.engine.initialize(this.options, () => {
682
- (0, user_manager_ua_1.bindRoleSet)(this.userManager, this.engine.addressSpace);
683
- setImmediate(() => {
684
- this.emit("post_initialize");
685
- done();
686
- });
687
- });
688
- })
689
- .catch((err) => {
690
- done(err);
691
- });
692
- }
693
- start(...args) {
694
- const done = args[0];
695
- const tasks = [];
696
- tasks.push((0, util_1.callbackify)(node_opcua_hostname_1.extractFullyQualifiedDomainName));
697
- if (!this.initialized) {
698
- tasks.push((callback) => {
699
- this.initialize(callback);
700
- });
701
- }
702
- tasks.push((callback) => {
703
- super.start((err) => {
704
- if (err) {
705
- this.shutdown((/*err2*/ err2) => {
706
- callback(err);
707
- });
708
- }
709
- else {
710
- // we start the registration process asynchronously
711
- // as we want to make server immediately available
712
- this.registerServerManager.start(() => {
713
- /* empty */
714
- });
715
- setImmediate(callback);
716
- }
717
- });
718
- });
719
- async.series(tasks, done);
720
- }
721
- shutdown(...args) {
722
- const timeout = args.length === 1 ? OPCUAServer.defaultShutdownTimeout : args[0];
723
- const callback = (args.length === 1 ? args[0] : args[1]);
724
- (0, node_opcua_assert_1.assert)(typeof callback === "function");
725
- debugLog("OPCUAServer#shutdown (timeout = ", timeout, ")");
726
- /* istanbul ignore next */
727
- if (!this.engine) {
728
- return callback();
729
- }
730
- (0, node_opcua_assert_1.assert)(this.engine);
731
- if (!this.engine.isStarted()) {
732
- // server may have been shot down already , or may have fail to start !!
733
- const err = new Error("OPCUAServer#shutdown failure ! server doesn't seems to be started yet");
734
- return callback(err);
735
- }
736
- this.userCertificateManager.dispose();
737
- this.engine.setServerState(node_opcua_common_1.ServerState.Shutdown);
738
- const shutdownTime = new Date(Date.now() + timeout);
739
- this.engine.setShutdownTime(shutdownTime);
740
- debugLog("OPCUAServer is now unregistering itself from the discovery server " + this.buildInfo);
741
- this.registerServerManager.stop((err) => {
742
- debugLog("OPCUAServer unregistered from discovery server", err);
743
- setTimeout(() => __awaiter(this, void 0, void 0, function* () {
744
- yield this.engine.shutdown();
745
- debugLog("OPCUAServer#shutdown: started");
746
- base_server_1.OPCUABaseServer.prototype.shutdown.call(this, (err1) => {
747
- debugLog("OPCUAServer#shutdown: completed");
748
- this.dispose();
749
- callback(err1);
750
- });
751
- }), timeout);
752
- });
753
- }
754
- dispose() {
755
- for (const endpoint of this.endpoints) {
756
- endpoint.dispose();
757
- }
758
- this.endpoints = [];
759
- this.removeAllListeners();
760
- if (this.registerServerManager) {
761
- this.registerServerManager.dispose();
762
- this.registerServerManager = undefined;
763
- }
764
- OPCUAServer.registry.unregister(this);
765
- /* istanbul ignore next */
766
- if (this.engine) {
767
- this.engine.dispose();
768
- }
769
- }
770
- raiseEvent(eventType, options) {
771
- /* istanbul ignore next */
772
- if (!this.engine.addressSpace) {
773
- errorLog("addressSpace missing");
774
- return;
775
- }
776
- const server = this.engine.addressSpace.findNode("Server");
777
- /* istanbul ignore next */
778
- if (!server) {
779
- // xx throw new Error("OPCUAServer#raiseEvent : cannot find Server object");
780
- return;
781
- }
782
- let eventTypeNode = eventType;
783
- if (typeof eventType === "string") {
784
- eventTypeNode = this.engine.addressSpace.findEventType(eventType);
785
- if (eventTypeNode) {
786
- return server.raiseEvent(eventTypeNode, options);
787
- }
788
- else {
789
- console.warn(" cannot find event type ", eventType);
790
- }
791
- }
792
- else {
793
- return server.raiseEvent(eventTypeNode, options);
794
- }
795
- }
796
- /**
797
- * create and register a new session
798
- * @internal
799
- */
800
- createSession(options) {
801
- /* istanbul ignore next */
802
- if (!this.engine) {
803
- throw new Error("Internal Error");
804
- }
805
- return this.engine.createSession(options);
806
- }
807
- /**
808
- * retrieve a session by authentication token
809
- * @internal
810
- */
811
- getSession(authenticationToken, activeOnly) {
812
- return this.engine ? this.engine.getSession(authenticationToken, activeOnly) : null;
813
- }
814
- /**
815
- *
816
- * @param channel
817
- * @param clientCertificate
818
- * @param clientNonce
819
- * @internal
820
- */
821
- computeServerSignature(channel, clientCertificate, clientNonce) {
822
- return (0, node_opcua_secure_channel_1.computeSignature)(clientCertificate, clientNonce, this.getPrivateKey(), channel.messageBuilder.securityPolicy);
823
- }
824
- /**
825
- *
826
- * @param session
827
- * @param channel
828
- * @param clientSignature
829
- * @internal
830
- */
831
- verifyClientSignature(session, channel, clientSignature) {
832
- const clientCertificate = channel.receiverCertificate;
833
- const securityPolicy = channel.messageBuilder.securityPolicy;
834
- const serverCertificate = this.getCertificate();
835
- const result = (0, node_opcua_secure_channel_1.verifySignature)(serverCertificate, session.nonce, clientSignature, clientCertificate, securityPolicy);
836
- return result;
837
- }
838
- isValidUserNameIdentityToken(channel, session, userTokenPolicy, userIdentityToken, userTokenSignature, callback) {
839
- (0, node_opcua_assert_1.assert)(userIdentityToken instanceof node_opcua_service_session_1.UserNameIdentityToken);
840
- const securityPolicy = adjustSecurityPolicy(channel, userTokenPolicy.securityPolicyUri);
841
- if (securityPolicy === node_opcua_secure_channel_1.SecurityPolicy.None) {
842
- return callback(null, node_opcua_status_code_1.StatusCodes.Good);
843
- }
844
- const cryptoFactory = (0, node_opcua_secure_channel_1.getCryptoFactory)(securityPolicy);
845
- /* istanbul ignore next */
846
- if (!cryptoFactory) {
847
- return callback(null, node_opcua_status_code_1.StatusCodes.BadSecurityPolicyRejected);
848
- }
849
- /* istanbul ignore next */
850
- if (userIdentityToken.encryptionAlgorithm !== cryptoFactory.asymmetricEncryptionAlgorithm) {
851
- errorLog("invalid encryptionAlgorithm");
852
- errorLog("userTokenPolicy", userTokenPolicy.toString());
853
- errorLog("userTokenPolicy", userIdentityToken.toString());
854
- return callback(null, node_opcua_status_code_1.StatusCodes.BadIdentityTokenInvalid);
855
- }
856
- const userName = userIdentityToken.userName;
857
- const password = userIdentityToken.password;
858
- if (!userName || !password) {
859
- return callback(null, node_opcua_status_code_1.StatusCodes.BadIdentityTokenInvalid);
860
- }
861
- return callback(null, node_opcua_status_code_1.StatusCodes.Good);
862
- }
863
- isValidX509IdentityToken(channel, session, userTokenPolicy, userIdentityToken, userTokenSignature, callback) {
864
- (0, node_opcua_assert_1.assert)(userIdentityToken instanceof node_opcua_service_session_1.X509IdentityToken);
865
- (0, node_opcua_assert_1.assert)(typeof callback === "function");
866
- const securityPolicy = adjustSecurityPolicy(channel, userTokenPolicy.securityPolicyUri);
867
- const cryptoFactory = (0, node_opcua_secure_channel_1.getCryptoFactory)(securityPolicy);
868
- /* istanbul ignore next */
869
- if (!cryptoFactory) {
870
- return callback(null, node_opcua_status_code_1.StatusCodes.BadSecurityPolicyRejected);
871
- }
872
- if (!userTokenSignature || !userTokenSignature.signature) {
873
- this.raiseEvent("AuditCreateSessionEventType", {});
874
- return callback(null, node_opcua_status_code_1.StatusCodes.BadUserSignatureInvalid);
875
- }
876
- if (userIdentityToken.policyId !== userTokenPolicy.policyId) {
877
- errorLog("invalid encryptionAlgorithm");
878
- errorLog("userTokenPolicy", userTokenPolicy.toString());
879
- errorLog("userTokenPolicy", userIdentityToken.toString());
880
- return callback(null, node_opcua_status_code_1.StatusCodes.BadSecurityPolicyRejected);
881
- }
882
- const certificate = userIdentityToken.certificateData; /* as Certificate*/
883
- const nonce = session.nonce;
884
- const serverCertificate = this.getCertificate();
885
- (0, node_opcua_assert_1.assert)(serverCertificate instanceof Buffer);
886
- (0, node_opcua_assert_1.assert)(certificate instanceof Buffer, "expecting certificate to be a Buffer");
887
- (0, node_opcua_assert_1.assert)(nonce instanceof Buffer, "expecting nonce to be a Buffer");
888
- (0, node_opcua_assert_1.assert)(userTokenSignature.signature instanceof Buffer, "expecting userTokenSignature to be a Buffer");
889
- // verify proof of possession by checking certificate signature & server nonce correctness
890
- if (!(0, node_opcua_secure_channel_1.verifySignature)(serverCertificate, nonce, userTokenSignature, certificate, securityPolicy)) {
891
- return callback(null, node_opcua_status_code_1.StatusCodes.BadUserSignatureInvalid);
892
- }
893
- // verify if certificate is Valid
894
- this.userCertificateManager.checkCertificate(certificate, (err, certificateStatus) => {
895
- /* istanbul ignore next */
896
- if (err) {
897
- return callback(err);
898
- }
899
- if (this.isAuditing) {
900
- switch (certificateStatus) {
901
- case node_opcua_status_code_1.StatusCodes.Good:
902
- break;
903
- case node_opcua_status_code_1.StatusCodes.BadCertificateUntrusted:
904
- this.raiseEvent("AuditCertificateUntrustedEventType", {
905
- certificate: { dataType: node_opcua_variant_1.DataType.ByteString, value: certificate },
906
- sourceName: { dataType: node_opcua_variant_1.DataType.String, value: "Security/Certificate" }
907
- });
908
- break;
909
- case node_opcua_status_code_1.StatusCodes.BadCertificateTimeInvalid:
910
- case node_opcua_status_code_1.StatusCodes.BadCertificateIssuerTimeInvalid:
911
- this.raiseEvent("AuditCertificateExpiredEventType", {
912
- certificate: { dataType: node_opcua_variant_1.DataType.ByteString, value: certificate },
913
- sourceName: { dataType: node_opcua_variant_1.DataType.String, value: "Security/Certificate" },
914
- comment: { dataType: node_opcua_variant_1.DataType.String, value: certificateStatus.toString() }
915
- });
916
- break;
917
- case node_opcua_status_code_1.StatusCodes.BadCertificateRevoked:
918
- case node_opcua_status_code_1.StatusCodes.BadCertificateRevocationUnknown:
919
- case node_opcua_status_code_1.StatusCodes.BadCertificateIssuerRevocationUnknown:
920
- this.raiseEvent("AuditCertificateRevokedEventType", {
921
- certificate: { dataType: node_opcua_variant_1.DataType.ByteString, value: certificate },
922
- sourceName: { dataType: node_opcua_variant_1.DataType.String, value: "Security/Certificate" },
923
- comment: { dataType: node_opcua_variant_1.DataType.String, value: certificateStatus.toString() }
924
- });
925
- break;
926
- case node_opcua_status_code_1.StatusCodes.BadCertificateIssuerUseNotAllowed:
927
- case node_opcua_status_code_1.StatusCodes.BadCertificateUseNotAllowed:
928
- case node_opcua_status_code_1.StatusCodes.BadSecurityChecksFailed:
929
- this.raiseEvent("AuditCertificateMismatchEventType", {
930
- certificate: { dataType: node_opcua_variant_1.DataType.ByteString, value: certificate },
931
- sourceName: { dataType: node_opcua_variant_1.DataType.String, value: "Security/Certificate" },
932
- comment: { dataType: node_opcua_variant_1.DataType.String, value: certificateStatus.toString() }
933
- });
934
- break;
935
- }
936
- }
937
- if (node_opcua_status_code_1.StatusCodes.BadCertificateUntrusted === certificateStatus ||
938
- node_opcua_status_code_1.StatusCodes.BadCertificateTimeInvalid === certificateStatus ||
939
- node_opcua_status_code_1.StatusCodes.BadCertificateIssuerTimeInvalid === certificateStatus ||
940
- node_opcua_status_code_1.StatusCodes.BadCertificateIssuerUseNotAllowed === certificateStatus ||
941
- node_opcua_status_code_1.StatusCodes.BadCertificateIssuerRevocationUnknown === certificateStatus ||
942
- node_opcua_status_code_1.StatusCodes.BadCertificateRevocationUnknown === certificateStatus ||
943
- node_opcua_status_code_1.StatusCodes.BadCertificateRevoked === certificateStatus ||
944
- node_opcua_status_code_1.StatusCodes.BadCertificateUseNotAllowed === certificateStatus ||
945
- node_opcua_status_code_1.StatusCodes.BadSecurityChecksFailed === certificateStatus ||
946
- node_opcua_status_code_1.StatusCodes.Good !== certificateStatus) {
947
- debugLog("isValidX509IdentityToken => certificateStatus = ", certificateStatus === null || certificateStatus === void 0 ? void 0 : certificateStatus.toString());
948
- return callback(null, node_opcua_status_code_1.StatusCodes.BadIdentityTokenRejected);
949
- }
950
- if (node_opcua_status_code_1.StatusCodes.Good !== certificateStatus) {
951
- (0, node_opcua_assert_1.assert)(certificateStatus instanceof node_opcua_status_code_1.StatusCode);
952
- return callback(null, certificateStatus);
953
- // return callback(null, StatusCodes.BadIdentityTokenInvalid);
954
- }
955
- // verify if certificate is truster or rejected
956
- // todo: StatusCodes.BadCertificateUntrusted
957
- // store untrusted certificate to rejected folder
958
- // todo:
959
- return callback(null, node_opcua_status_code_1.StatusCodes.Good);
960
- });
961
- }
962
- /**
963
- * @internal
964
- */
965
- userNameIdentityTokenAuthenticateUser(channel, session, userTokenPolicy, userIdentityToken, callback) {
966
- (0, node_opcua_assert_1.assert)(userIdentityToken instanceof node_opcua_service_session_1.UserNameIdentityToken);
967
- // assert(this.isValidUserNameIdentityToken(channel, session, userTokenPolicy, userIdentityToken));
968
- const securityPolicy = adjustSecurityPolicy(channel, userTokenPolicy.securityPolicyUri);
969
- const userName = userIdentityToken.userName;
970
- let password = userIdentityToken.password;
971
- // decrypt password if necessary
972
- if (securityPolicy === node_opcua_secure_channel_1.SecurityPolicy.None) {
973
- // not good, password was sent in clear text ...
974
- password = password.toString();
975
- }
976
- else {
977
- const serverPrivateKey = this.getPrivateKey();
978
- const serverNonce = session.nonce;
979
- (0, node_opcua_assert_1.assert)(serverNonce instanceof Buffer);
980
- const cryptoFactory = (0, node_opcua_secure_channel_1.getCryptoFactory)(securityPolicy);
981
- /* istanbul ignore next */
982
- if (!cryptoFactory) {
983
- return callback(new Error(" Unsupported security Policy"));
984
- }
985
- const buff = cryptoFactory.asymmetricDecrypt(password, serverPrivateKey);
986
- // server certificate may be invalid and asymmetricDecrypt may fail
987
- if (!buff || buff.length < 4) {
988
- async.setImmediate(() => callback(null, false));
989
- return;
990
- }
991
- const length = buff.readUInt32LE(0) - serverNonce.length;
992
- password = buff.slice(4, 4 + length).toString("utf-8");
993
- }
994
- this.userManager
995
- .isValidUser(session, userName, password)
996
- .then((isValid) => callback(null, isValid))
997
- .catch((err) => callback(err));
998
- }
999
- /**
1000
- * @internal
1001
- */
1002
- isValidUserIdentityToken(channel, session, userIdentityToken, userTokenSignature, endpointDescription, callback) {
1003
- (0, node_opcua_assert_1.assert)(typeof callback === "function");
1004
- /* istanbul ignore next */
1005
- if (!userIdentityToken) {
1006
- throw new Error("Invalid token");
1007
- }
1008
- const userTokenType = getTokenType(userIdentityToken);
1009
- const userTokenPolicy = findUserTokenByPolicy(endpointDescription, userTokenType, userIdentityToken.policyId);
1010
- if (!userTokenPolicy) {
1011
- // cannot find token with this policyId
1012
- return callback(null, node_opcua_status_code_1.StatusCodes.BadIdentityTokenInvalid);
1013
- }
1014
- //
1015
- if (userIdentityToken instanceof node_opcua_service_session_1.UserNameIdentityToken) {
1016
- return this.isValidUserNameIdentityToken(channel, session, userTokenPolicy, userIdentityToken, userTokenSignature, callback);
1017
- }
1018
- if (userIdentityToken instanceof node_opcua_service_session_1.X509IdentityToken) {
1019
- return this.isValidX509IdentityToken(channel, session, userTokenPolicy, userIdentityToken, userTokenSignature, callback);
1020
- }
1021
- return callback(null, node_opcua_status_code_1.StatusCodes.Good);
1022
- }
1023
- /**
1024
- *
1025
- * @internal
1026
- * @param channel
1027
- * @param session
1028
- * @param userIdentityToken
1029
- * @param callback
1030
- * @returns {*}
1031
- */
1032
- isUserAuthorized(channel, session, userIdentityToken, callback) {
1033
- (0, node_opcua_assert_1.assert)(userIdentityToken);
1034
- (0, node_opcua_assert_1.assert)(typeof callback === "function");
1035
- const userTokenType = getTokenType(userIdentityToken);
1036
- const userTokenPolicy = findUserTokenByPolicy(session.getEndpointDescription(), userTokenType, userIdentityToken.policyId);
1037
- /** istanbul ignore next */
1038
- if (!userTokenPolicy) {
1039
- return callback(null, false);
1040
- }
1041
- // find if a userToken exists
1042
- if (userIdentityToken instanceof node_opcua_service_session_1.UserNameIdentityToken) {
1043
- return this.userNameIdentityTokenAuthenticateUser(channel, session, userTokenPolicy, userIdentityToken, callback);
1044
- }
1045
- async.setImmediate(callback.bind(null, null, true));
1046
- }
1047
- makeServerNonce() {
1048
- return crypto.randomBytes(32);
1049
- }
1050
- // session services
1051
- // eslint-disable-next-line max-statements
1052
- _on_CreateSessionRequest(message, channel) {
1053
- return __awaiter(this, void 0, void 0, function* () {
1054
- const request = message.request;
1055
- (0, node_opcua_assert_1.assert)(request instanceof node_opcua_service_session_1.CreateSessionRequest);
1056
- function rejectConnection(server, statusCode) {
1057
- server.engine.incrementSecurityRejectedSessionCount();
1058
- const response1 = new node_opcua_service_session_1.CreateSessionResponse({
1059
- responseHeader: { serviceResult: statusCode }
1060
- });
1061
- channel.send_response("MSG", response1, message);
1062
- // and close !
1063
- }
1064
- // From OPCUA V1.03 Part 4 5.6.2 CreateSession
1065
- // A Server application should limit the number of Sessions. To protect against misbehaving Clients and denial
1066
- // of service attacks, the Server shall close the oldest Session that is not activated before reaching the
1067
- // maximum number of supported Sessions
1068
- if (this.currentSessionCount >= this.engine.serverCapabilities.maxSessions) {
1069
- yield _attempt_to_close_some_old_unactivated_session(this);
1070
- }
1071
- // check if session count hasn't reach the maximum allowed sessions
1072
- if (this.currentSessionCount >= this.engine.serverCapabilities.maxSessions) {
1073
- return rejectConnection(this, node_opcua_status_code_1.StatusCodes.BadTooManySessions);
1074
- }
1075
- // Release 1.03 OPC Unified Architecture, Part 4 page 24 - CreateSession Parameters
1076
- // client should prove a sessionName
1077
- // Session name is a Human readable string that identifies the Session. The Server makes this name and the
1078
- // sessionId visible in its AddressSpace for diagnostic purposes. The Client should provide a name that is
1079
- // unique for the instance of the Client.
1080
- // If this parameter is not specified the Server shall assign a value.
1081
- if (utils.isNullOrUndefined(request.sessionName)) {
1082
- // see also #198
1083
- // let's the server assign a sessionName for this lazy client.
1084
- debugLog("assigning OPCUAServer.fallbackSessionName because client's sessionName is null ", OPCUAServer.fallbackSessionName);
1085
- request.sessionName = OPCUAServer.fallbackSessionName;
1086
- }
1087
- // Duration Requested maximum number of milliseconds that a Session should remain open without activity.
1088
- // If the Client fails to issue a Service request within this interval, then the Server shall automatically
1089
- // terminate the Client Session.
1090
- const revisedSessionTimeout = _adjust_session_timeout(request.requestedSessionTimeout);
1091
- // Release 1.02 page 27 OPC Unified Architecture, Part 4: CreateSession.clientNonce
1092
- // A random number that should never be used in any other request. This number shall have a minimum length of 32
1093
- // bytes. Profiles may increase the required length. The Server shall use this value to prove possession of
1094
- // its application instance Certificate in the response.
1095
- if (!request.clientNonce || request.clientNonce.length < 32) {
1096
- if (channel.securityMode !== node_opcua_secure_channel_1.MessageSecurityMode.None) {
1097
- errorLog(chalk.red("SERVER with secure connection: Missing or invalid client Nonce "), request.clientNonce && request.clientNonce.toString("hex"));
1098
- return rejectConnection(this, node_opcua_status_code_1.StatusCodes.BadNonceInvalid);
1099
- }
1100
- }
1101
- if ((0, node_opcua_secure_channel_1.nonceAlreadyBeenUsed)(request.clientNonce)) {
1102
- errorLog(chalk.red("SERVER with secure connection: None has already been used"), request.clientNonce && request.clientNonce.toString("hex"));
1103
- return rejectConnection(this, node_opcua_status_code_1.StatusCodes.BadNonceInvalid);
1104
- }
1105
- // check application spoofing
1106
- // check if applicationUri in createSessionRequest matches applicationUri in client Certificate
1107
- if (!validate_applicationUri(channel, request)) {
1108
- return rejectConnection(this, node_opcua_status_code_1.StatusCodes.BadCertificateUriInvalid);
1109
- }
1110
- const { errCode, endpoint } = validate_security_endpoint(this, request, channel);
1111
- if (errCode !== node_opcua_status_code_1.StatusCodes.Good) {
1112
- return rejectConnection(this, errCode);
1113
- }
1114
- // see Release 1.02 27 OPC Unified Architecture, Part 4
1115
- const session = this.createSession({
1116
- clientDescription: request.clientDescription,
1117
- sessionTimeout: revisedSessionTimeout
1118
- });
1119
- session.endpoint = endpoint;
1120
- (0, node_opcua_assert_1.assert)(session);
1121
- (0, node_opcua_assert_1.assert)(session.sessionTimeout === revisedSessionTimeout);
1122
- session.clientDescription = request.clientDescription;
1123
- session.sessionName = request.sessionName || `<unknown session name ${unnamed_session_count++}>`;
1124
- // Depending upon on the SecurityPolicy and the SecurityMode of the SecureChannel, the exchange of
1125
- // ApplicationInstanceCertificates and Nonces may be optional and the signatures may be empty. See
1126
- // Part 7 for the definition of SecurityPolicies and the handling of these parameters
1127
- // serverNonce:
1128
- // A random number that should never be used in any other request.
1129
- // This number shall have a minimum length of 32 bytes.
1130
- // The Client shall use this value to prove possession of its application instance
1131
- // Certificate in the ActivateSession request.
1132
- // This value may also be used to prove possession of the userIdentityToken it
1133
- // specified in the ActivateSession request.
1134
- //
1135
- // ( this serverNonce will only be used up to the _on_ActivateSessionRequest
1136
- // where a new nonce will be created)
1137
- session.nonce = this.makeServerNonce();
1138
- session.channelId = channel.channelId;
1139
- session._attach_channel(channel);
1140
- const serverCertificateChain = this.getCertificateChain();
1141
- const hasEncryption = true;
1142
- // If the securityPolicyUri is None and none of the UserTokenPolicies requires encryption
1143
- if (session.channel.securityMode === node_opcua_secure_channel_1.MessageSecurityMode.None) {
1144
- // ToDo: Check that none of our insecure endpoint has a a UserTokenPolicy that require encryption
1145
- // and set hasEncryption = false under this condition
1146
- }
1147
- const response = new node_opcua_service_session_1.CreateSessionResponse({
1148
- // A identifier which uniquely identifies the session.
1149
- sessionId: session.nodeId,
1150
- // A unique identifier assigned by the Server to the Session.
1151
- // The token used to authenticate the client in subsequent requests.
1152
- authenticationToken: session.authenticationToken,
1153
- revisedSessionTimeout,
1154
- serverNonce: session.nonce,
1155
- // serverCertificate: type ApplicationServerCertificate
1156
- // The application instance Certificate issued to the Server.
1157
- // A Server shall prove possession by using the private key to sign the Nonce provided
1158
- // by the Client in the request. The Client shall verify that this Certificate is the same as
1159
- // the one it used to create the SecureChannel.
1160
- // The ApplicationInstanceCertificate type is defined in OpCUA 1.03 part 4 - $7.2 page 108
1161
- // If the securityPolicyUri is None and none of the UserTokenPolicies requires
1162
- // encryption, the Server shall not send an ApplicationInstanceCertificate and the Client
1163
- // shall ignore the ApplicationInstanceCertificate.
1164
- serverCertificate: hasEncryption ? serverCertificateChain : undefined,
1165
- // The endpoints provided by the server.
1166
- // The Server shall return a set of EndpointDescriptions available for the serverUri
1167
- // specified in the request.[...]
1168
- // The Client shall verify this list with the list from a Discovery Endpoint if it used a Discovery
1169
- // Endpoint to fetch the EndpointDescriptions.
1170
- // It is recommended that Servers only include the endpointUrl, securityMode,
1171
- // securityPolicyUri, userIdentityTokens, transportProfileUri and securityLevel with all
1172
- // other parameters set to null. Only the recommended parameters shall be verified by
1173
- // the client.
1174
- serverEndpoints: _serverEndpointsForCreateSessionResponse(this, session.endpoint.endpointUrl, request.serverUri),
1175
- // This parameter is deprecated and the array shall be empty.
1176
- serverSoftwareCertificates: null,
1177
- // This is a signature generated with the private key associated with the
1178
- // serverCertificate. This parameter is calculated by appending the clientNonce to the
1179
- // clientCertificate and signing the resulting sequence of bytes.
1180
- // The SignatureAlgorithm shall be the AsymmetricSignatureAlgorithm specified in the
1181
- // SecurityPolicy for the Endpoint.
1182
- // The SignatureData type is defined in 7.30.
1183
- serverSignature: this.computeServerSignature(channel, request.clientCertificate, request.clientNonce),
1184
- // The maximum message size accepted by the server
1185
- // The Client Communication Stack should return a Bad_RequestTooLarge error to the
1186
- // application if a request message exceeds this limit.
1187
- // The value zero indicates that this parameter is not used.
1188
- maxRequestMessageSize: 0x4000000
1189
- });
1190
- this.emit("create_session", session);
1191
- session.on("session_closed", (session1, deleteSubscriptions, reason) => {
1192
- (0, node_opcua_assert_1.assert)(typeof reason === "string");
1193
- if (this.isAuditing) {
1194
- (0, node_opcua_assert_1.assert)(reason === "Timeout" || reason === "Terminated" || reason === "CloseSession" || reason === "Forcing");
1195
- const sourceName = "Session/" + reason;
1196
- this.raiseEvent("AuditSessionEventType", {
1197
- /* part 5 - 6.4.3 AuditEventType */
1198
- actionTimeStamp: { dataType: "DateTime", value: new Date() },
1199
- status: { dataType: "Boolean", value: true },
1200
- serverId: { dataType: "String", value: "" },
1201
- // ClientAuditEntryId contains the human-readable AuditEntryId defined in Part 3.
1202
- clientAuditEntryId: { dataType: "String", value: "" },
1203
- // The ClientUserId identifies the user of the client requesting an action. The ClientUserId can be
1204
- // obtained from the UserIdentityToken passed in the ActivateSession call.
1205
- clientUserId: { dataType: "String", value: "" },
1206
- sourceName: { dataType: "String", value: sourceName },
1207
- /* part 5 - 6.4.7 AuditSessionEventType */
1208
- sessionId: { dataType: "NodeId", value: session1.nodeId }
1209
- });
1210
- }
1211
- this.emit("session_closed", session1, deleteSubscriptions);
1212
- });
1213
- if (this.isAuditing) {
1214
- // ------------------------------------------------------------------------------------------------------
1215
- this.raiseEvent("AuditCreateSessionEventType", {
1216
- /* part 5 - 6.4.3 AuditEventType */
1217
- actionTimeStamp: { dataType: "DateTime", value: new Date() },
1218
- status: { dataType: "Boolean", value: true },
1219
- serverId: { dataType: "String", value: "" },
1220
- // ClientAuditEntryId contains the human-readable AuditEntryId defined in Part 3.
1221
- clientAuditEntryId: { dataType: "String", value: "" },
1222
- // The ClientUserId identifies the user of the client requesting an action. The ClientUserId can be
1223
- // obtained from the UserIdentityToken passed in the ActivateSession call.
1224
- clientUserId: { dataType: "String", value: "" },
1225
- sourceName: { dataType: "String", value: "Session/CreateSession" },
1226
- /* part 5 - 6.4.7 AuditSessionEventType */
1227
- sessionId: { dataType: "NodeId", value: session.nodeId },
1228
- /* part 5 - 6.4.8 AuditCreateSessionEventType */
1229
- // SecureChannelId shall uniquely identify the SecureChannel. The application shall use the same
1230
- // identifier in all AuditEvents related to the Session Service Set (AuditCreateSessionEventType,
1231
- // AuditActivateSessionEventType and their subtypes) and the SecureChannel Service Set
1232
- // (AuditChannelEventType and its subtypes
1233
- secureChannelId: { dataType: "String", value: session.channel.channelId.toString() },
1234
- // Duration
1235
- revisedSessionTimeout: { dataType: "Duration", value: session.sessionTimeout },
1236
- // clientCertificate
1237
- clientCertificate: { dataType: "ByteString", value: session.channel.clientCertificate },
1238
- // clientCertificateThumbprint
1239
- clientCertificateThumbprint: {
1240
- dataType: "String",
1241
- value: thumbprint(session.channel.clientCertificate)
1242
- }
1243
- });
1244
- }
1245
- // -----------------------------------------------------------------------------------------------------------
1246
- (0, node_opcua_assert_1.assert)(response.authenticationToken);
1247
- channel.send_response("MSG", response, message);
1248
- });
1249
- }
1250
- // TODO : implement this:
1251
- //
1252
- // When the ActivateSession Service is called for the first time then the Server shall reject the request
1253
- // if the SecureChannel is not same as the one associated with the CreateSession request.
1254
- // Subsequent calls to ActivateSession may be associated with different SecureChannels. If this is the
1255
- // case then the Server shall verify that the Certificate the Client used to create the new
1256
- // SecureChannel is the same as the Certificate used to create the original SecureChannel. In addition,
1257
- // the Server shall verify that the Client supplied a UserIdentityToken that is identical to the token
1258
- // currently associated with the Session. Once the Server accepts the new SecureChannel it shall
1259
- // reject requests sent via the old SecureChannel.
1260
- /**
1261
- *
1262
- * @method _on_ActivateSessionRequest
1263
- * @private
1264
- *
1265
- *
1266
- */
1267
- _on_ActivateSessionRequest(message, channel) {
1268
- const request = message.request;
1269
- (0, node_opcua_assert_1.assert)(request instanceof node_opcua_service_session_1.ActivateSessionRequest);
1270
- // get session from authenticationToken
1271
- const authenticationToken = request.requestHeader.authenticationToken;
1272
- const session = this.getSession(authenticationToken);
1273
- function rejectConnection(server, statusCode) {
1274
- if (statusCode === node_opcua_status_code_1.StatusCodes.BadSessionIdInvalid) {
1275
- server.engine.incrementRejectedSessionCount();
1276
- }
1277
- else {
1278
- server.engine.incrementRejectedSessionCount();
1279
- server.engine.incrementSecurityRejectedSessionCount();
1280
- }
1281
- const response1 = new node_opcua_service_session_1.ActivateSessionResponse({ responseHeader: { serviceResult: statusCode } });
1282
- channel.send_response("MSG", response1, message);
1283
- // and close !
1284
- }
1285
- let response;
1286
- /* istanbul ignore next */
1287
- if (!session) {
1288
- // this may happen when the server has been restarted and a client tries to reconnect, thinking
1289
- // that the previous session may still be active
1290
- debugLog(chalk.yellow.bold(" Bad Session in _on_ActivateSessionRequest"), authenticationToken.toString());
1291
- return rejectConnection(this, node_opcua_status_code_1.StatusCodes.BadSessionIdInvalid);
1292
- }
1293
- // tslint:disable-next-line: no-unused-expression
1294
- session.keepAlive ? session.keepAlive() : void 0;
1295
- // OpcUA 1.02 part 3 $5.6.3.1 ActiveSession Set page 29
1296
- // When the ActivateSession Service is called f or the first time then the Server shall reject the request
1297
- // if the SecureChannel is not same as the one associated with the CreateSession request.
1298
- if (session.status === "new") {
1299
- // xx if (channel.session_nonce !== session.nonce) {
1300
- if (!channel_has_session(channel, session)) {
1301
- // it looks like session activation is being using a channel that is not the
1302
- // one that have been used to create the session
1303
- errorLog(" channel.sessionTokens === " + Object.keys(channel.sessionTokens).join(" "));
1304
- return rejectConnection(this, node_opcua_status_code_1.StatusCodes.BadSessionNotActivated);
1305
- }
1306
- }
1307
- // OpcUA 1.02 part 3 $5.6.3.1 ActiveSession Set page 29
1308
- // ... Subsequent calls to ActivateSession may be associated with different SecureChannels. If this is the
1309
- // case then the Server shall verify that the Certificate the Client used to create the new
1310
- // SecureChannel is the same as the Certificate used to create the original SecureChannel.
1311
- if (session.status === "active") {
1312
- if (session.channel.channelId !== channel.channelId) {
1313
- warningLog(" Session ", session.sessionName, " is being transferred from channel", chalk.cyan(session.channel.channelId.toString()), " to channel ", chalk.cyan(channel.channelId.toString()));
1314
- // session is being reassigned to a new Channel,
1315
- // we shall verify that the certificate used to create the Session is the same as the current
1316
- // channel certificate.
1317
- const old_channel_cert_thumbprint = thumbprint(session.channel.clientCertificate);
1318
- const new_channel_cert_thumbprint = thumbprint(channel.clientCertificate);
1319
- if (old_channel_cert_thumbprint !== new_channel_cert_thumbprint) {
1320
- return rejectConnection(this, node_opcua_status_code_1.StatusCodes.BadNoValidCertificates); // not sure about this code !
1321
- }
1322
- // ... In addition the Server shall verify that the Client supplied a UserIdentityToken that is
1323
- // identical to the token currently associated with the Session reassign session to new channel.
1324
- if (!sameIdentityToken(session.userIdentityToken, request.userIdentityToken)) {
1325
- return rejectConnection(this, node_opcua_status_code_1.StatusCodes.BadIdentityChangeNotSupported); // not sure about this code !
1326
- }
1327
- }
1328
- moveSessionToChannel(session, channel);
1329
- }
1330
- else if (session.status === "screwed") {
1331
- // session has been used before being activated => this should be detected and session should be dismissed.
1332
- return rejectConnection(this, node_opcua_status_code_1.StatusCodes.BadSessionClosed);
1333
- }
1334
- else if (session.status === "closed") {
1335
- warningLog(chalk.yellow.bold(" Bad Session Closed in _on_ActivateSessionRequest"), authenticationToken.toString());
1336
- return rejectConnection(this, node_opcua_status_code_1.StatusCodes.BadSessionClosed);
1337
- }
1338
- // verify clientSignature provided by the client
1339
- if (!this.verifyClientSignature(session, channel, request.clientSignature)) {
1340
- return rejectConnection(this, node_opcua_status_code_1.StatusCodes.BadApplicationSignatureInvalid);
1341
- }
1342
- // userIdentityToken may be missing , assume anonymous access then
1343
- request.userIdentityToken = request.userIdentityToken || createAnonymousIdentityToken(session.endpoint);
1344
- // check request.userIdentityToken is correct ( expected type and correctly formed)
1345
- this.isValidUserIdentityToken(channel, session, request.userIdentityToken, request.userTokenSignature, session.endpoint, (err, statusCode) => {
1346
- if (statusCode !== node_opcua_status_code_1.StatusCodes.Good) {
1347
- /* istanbul ignore next */
1348
- if (!(statusCode && statusCode instanceof node_opcua_status_code_1.StatusCode)) {
1349
- return rejectConnection(this, node_opcua_status_code_1.StatusCodes.BadCertificateInvalid);
1350
- }
1351
- return rejectConnection(this, statusCode);
1352
- }
1353
- session.userIdentityToken = request.userIdentityToken;
1354
- // check if user access is granted
1355
- this.isUserAuthorized(channel, session, request.userIdentityToken, (err1, authorized) => {
1356
- /* istanbul ignore next */
1357
- if (err1) {
1358
- return rejectConnection(this, node_opcua_status_code_1.StatusCodes.BadInternalError);
1359
- }
1360
- if (!authorized) {
1361
- return rejectConnection(this, node_opcua_status_code_1.StatusCodes.BadUserAccessDenied);
1362
- }
1363
- else {
1364
- // extract : OPC UA part 4 - 5.6.3
1365
- // Once used, a serverNonce cannot be used again. For that reason, the Server returns a new
1366
- // serverNonce each time the ActivateSession Service is called.
1367
- session.nonce = this.makeServerNonce();
1368
- session.status = "active";
1369
- response = new node_opcua_service_session_1.ActivateSessionResponse({ serverNonce: session.nonce });
1370
- channel.send_response("MSG", response, message);
1371
- const userIdentityTokenPasswordRemoved = (userIdentityToken) => {
1372
- const a = userIdentityToken.clone();
1373
- // remove password
1374
- a.password = "*************";
1375
- return a;
1376
- };
1377
- // send OPCUA Event Notification
1378
- // see part 5 : 6.4.3 AuditEventType
1379
- // 6.4.7 AuditSessionEventType
1380
- // 6.4.10 AuditActivateSessionEventType
1381
- (0, node_opcua_assert_1.assert)(session.nodeId); // sessionId
1382
- // xx assert(session.channel.clientCertificate instanceof Buffer);
1383
- (0, node_opcua_assert_1.assert)(session.sessionTimeout > 0);
1384
- if (this.isAuditing) {
1385
- this.raiseEvent("AuditActivateSessionEventType", {
1386
- /* part 5 - 6.4.3 AuditEventType */
1387
- actionTimeStamp: { dataType: "DateTime", value: new Date() },
1388
- status: { dataType: "Boolean", value: true },
1389
- serverId: { dataType: "String", value: "" },
1390
- // ClientAuditEntryId contains the human-readable AuditEntryId defined in Part 3.
1391
- clientAuditEntryId: { dataType: "String", value: "" },
1392
- // The ClientUserId identifies the user of the client requesting an action.
1393
- // The ClientUserId can be obtained from the UserIdentityToken passed in the
1394
- // ActivateSession call.
1395
- clientUserId: { dataType: "String", value: "cc" },
1396
- sourceName: { dataType: "String", value: "Session/ActivateSession" },
1397
- /* part 5 - 6.4.7 AuditSessionEventType */
1398
- sessionId: { dataType: "NodeId", value: session.nodeId },
1399
- /* part 5 - 6.4.10 AuditActivateSessionEventType */
1400
- clientSoftwareCertificates: {
1401
- arrayType: node_opcua_variant_2.VariantArrayType.Array,
1402
- dataType: "ExtensionObject" /* SignedSoftwareCertificate */,
1403
- value: []
1404
- },
1405
- // UserIdentityToken reflects the userIdentityToken parameter of the ActivateSession
1406
- // Service call.
1407
- // For Username/Password tokens the password should NOT be included.
1408
- userIdentityToken: {
1409
- dataType: "ExtensionObject" /* UserIdentityToken */,
1410
- value: userIdentityTokenPasswordRemoved(session.userIdentityToken)
1411
- },
1412
- // SecureChannelId shall uniquely identify the SecureChannel. The application shall
1413
- // use the same identifier in all AuditEvents related to the Session Service Set
1414
- // (AuditCreateSessionEventType, AuditActivateSessionEventType and their subtypes) and
1415
- // the SecureChannel Service Set (AuditChannelEventType and its subtypes).
1416
- secureChannelId: { dataType: "String", value: session.channel.channelId.toString() }
1417
- });
1418
- }
1419
- this.emit("session_activated", session, userIdentityTokenPasswordRemoved);
1420
- }
1421
- });
1422
- });
1423
- }
1424
- prepare(message, channel) {
1425
- const request = message.request;
1426
- // --- check that session is correct
1427
- const authenticationToken = request.requestHeader.authenticationToken;
1428
- const session = this.getSession(authenticationToken, /*activeOnly*/ true);
1429
- if (!session) {
1430
- message.session_statusCode = node_opcua_status_code_1.StatusCodes.BadSessionIdInvalid;
1431
- return;
1432
- }
1433
- message.session = session;
1434
- // --- check that provided session matches session attached to channel
1435
- if (channel.channelId !== session.channelId) {
1436
- if (!(request instanceof node_opcua_service_session_1.ActivateSessionRequest)) {
1437
- errorLog(chalk.red.bgWhite("ERROR: channel.channelId !== session.channelId on processing request " + request.constructor.name), channel.channelId, session.channelId);
1438
- }
1439
- message.session_statusCode = node_opcua_status_code_1.StatusCodes.BadSecureChannelIdInvalid;
1440
- }
1441
- else if (channel_has_session(channel, session)) {
1442
- message.session_statusCode = node_opcua_status_code_1.StatusCodes.Good;
1443
- }
1444
- else {
1445
- // session ma y have been moved to a different channel
1446
- message.session_statusCode = node_opcua_status_code_1.StatusCodes.BadSecureChannelIdInvalid;
1447
- }
1448
- }
1449
- /**
1450
- * ensure that action is performed on a valid session object,
1451
- * @method _apply_on_SessionObject
1452
- * @param ResponseClass the constructor of the response Class
1453
- * @param message
1454
- * @param channel
1455
- * @param actionToPerform
1456
- * @param actionToPerform.session {ServerSession}
1457
- * @param actionToPerform.sendResponse
1458
- * @param actionToPerform.sendResponse.response
1459
- * @param actionToPerform.sendError
1460
- * @param actionToPerform.sendError.statusCode
1461
- * @param actionToPerform.sendError.diagnostics
1462
- *
1463
- * @private
1464
- */
1465
- _apply_on_SessionObject(ResponseClass, message, channel, actionToPerform) {
1466
- return __awaiter(this, void 0, void 0, function* () {
1467
- (0, node_opcua_assert_1.assert)(typeof actionToPerform === "function");
1468
- function sendResponse(response1) {
1469
- try {
1470
- (0, node_opcua_assert_1.assert)(response1 instanceof ResponseClass || response1 instanceof node_opcua_types_1.ServiceFault);
1471
- if (message.session) {
1472
- const counterName = ResponseClass.name.replace("Response", "");
1473
- message.session.incrementRequestTotalCounter(counterName);
1474
- }
1475
- return channel.send_response("MSG", response1, message);
1476
- }
1477
- catch (err) {
1478
- warningLog(err);
1479
- // istanbul ignore next
1480
- if (err instanceof Error) {
1481
- // istanbul ignore next
1482
- errorLog("Internal error in issuing response\nplease contact support@sterfive.com", message.request.toString(), "\n", response1.toString());
1483
- }
1484
- // istanbul ignore next
1485
- throw err;
1486
- }
1487
- }
1488
- function sendError(statusCode) {
1489
- if (message.session) {
1490
- message.session.incrementRequestErrorCounter(ResponseClass.name.replace("Response", ""));
1491
- }
1492
- return g_sendError(channel, message, ResponseClass, statusCode);
1493
- }
1494
- let response;
1495
- /* istanbul ignore next */
1496
- if (!message.session || message.session_statusCode !== node_opcua_status_code_1.StatusCodes.Good) {
1497
- const errMessage = "INVALID SESSION !! ";
1498
- response = new ResponseClass({ responseHeader: { serviceResult: message.session_statusCode } });
1499
- debugLog(chalk.red.bold(errMessage), chalk.yellow(message.session_statusCode.toString()), response.constructor.name);
1500
- return sendResponse(response);
1501
- }
1502
- (0, node_opcua_assert_1.assert)(message.session_statusCode === node_opcua_status_code_1.StatusCodes.Good);
1503
- // OPC UA Specification 1.02 part 4 page 26
1504
- // When a Session is terminated, all outstanding requests on the Session are aborted and
1505
- // Bad_SessionClosed StatusCodes are returned to the Client. In addition, the Server deletes the entry
1506
- // for the Client from its SessionDiagnostics Array Variable and notifies any other Clients who were
1507
- // subscribed to this entry.
1508
- if (message.session.status === "closed") {
1509
- // note : use StatusCodes.BadSessionClosed , for pending message for this session
1510
- return sendError(node_opcua_status_code_1.StatusCodes.BadSessionIdInvalid);
1511
- }
1512
- if (message.session.status === "new") {
1513
- // mark session as being screwed ! so it cannot be activated anymore
1514
- message.session.status = "screwed";
1515
- return sendError(node_opcua_status_code_1.StatusCodes.BadSessionNotActivated);
1516
- }
1517
- if (message.session.status !== "active") {
1518
- // mark session as being screwed ! so it cannot be activated anymore
1519
- message.session.status = "screwed";
1520
- // note : use StatusCodes.BadSessionClosed , for pending message for this session
1521
- return sendError(node_opcua_status_code_1.StatusCodes.BadSessionIdInvalid);
1522
- }
1523
- // lets also reset the session watchdog so it doesn't
1524
- // (Sessions are terminated by the Server automatically if the Client fails to issue a Service
1525
- // request on the Session within the timeout period negotiated by the Server in the
1526
- // CreateSession Service response. )
1527
- if (message.session.keepAlive) {
1528
- (0, node_opcua_assert_1.assert)(typeof message.session.keepAlive === "function");
1529
- message.session.keepAlive();
1530
- }
1531
- message.session.incrementTotalRequestCount();
1532
- yield actionToPerform(message.session, sendResponse, sendError);
1533
- });
1534
- }
1535
- _apply_on_Subscription(ResponseClass, message, channel, actionToPerform) {
1536
- return __awaiter(this, void 0, void 0, function* () {
1537
- (0, node_opcua_assert_1.assert)(typeof actionToPerform === "function");
1538
- const request = message.request;
1539
- (0, node_opcua_assert_1.assert)(Object.prototype.hasOwnProperty.call(request, "subscriptionId"));
1540
- this._apply_on_SessionObject(ResponseClass, message, channel, (session, sendResponse, sendError) => __awaiter(this, void 0, void 0, function* () {
1541
- const subscription = session.getSubscription(request.subscriptionId);
1542
- if (!subscription) {
1543
- return sendError(node_opcua_status_code_1.StatusCodes.BadSubscriptionIdInvalid);
1544
- }
1545
- subscription.resetLifeTimeAndKeepAliveCounters();
1546
- yield actionToPerform(session, subscription, sendResponse, sendError);
1547
- }));
1548
- });
1549
- }
1550
- _apply_on_SubscriptionIds(ResponseClass, message, channel, actionToPerform) {
1551
- (0, node_opcua_assert_1.assert)(typeof actionToPerform === "function");
1552
- const request = message.request;
1553
- (0, node_opcua_assert_1.assert)(Object.prototype.hasOwnProperty.call(request, "subscriptionIds"));
1554
- this._apply_on_SessionObject(ResponseClass, message, channel, (session, sendResponse, sendError) => __awaiter(this, void 0, void 0, function* () {
1555
- const subscriptionIds = request.subscriptionIds;
1556
- if (!request.subscriptionIds || request.subscriptionIds.length === 0) {
1557
- return sendError(node_opcua_status_code_1.StatusCodes.BadNothingToDo);
1558
- }
1559
- const results = subscriptionIds.map((subscriptionId) => actionToPerform(session, subscriptionId));
1560
- // resolve potential pending promises ....
1561
- for (let i = 0; i < results.length; i++) {
1562
- if (results[i].then) {
1563
- results[i] = yield results[i];
1564
- }
1565
- }
1566
- const response = new ResponseClass({
1567
- responseHeader: {
1568
- serviceResult: request.subscriptionIds.length > this.engine.serverCapabilities.maxSubscriptionsPerSession
1569
- ? node_opcua_status_code_1.StatusCodes.BadTooManyOperations
1570
- : node_opcua_status_code_1.StatusCodes.Good
1571
- },
1572
- results
1573
- });
1574
- sendResponse(response);
1575
- }));
1576
- }
1577
- _apply_on_Subscriptions(ResponseClass, message, channel, actionToPerform) {
1578
- this._apply_on_SubscriptionIds(ResponseClass, message, channel, (session, subscriptionId) => __awaiter(this, void 0, void 0, function* () {
1579
- /* istanbul ignore next */
1580
- if (isSubscriptionIdInvalid(subscriptionId)) {
1581
- return node_opcua_status_code_1.StatusCodes.BadSubscriptionIdInvalid;
1582
- }
1583
- const subscription = session.getSubscription(subscriptionId);
1584
- if (!subscription) {
1585
- return node_opcua_status_code_1.StatusCodes.BadSubscriptionIdInvalid;
1586
- }
1587
- return actionToPerform(session, subscription);
1588
- }));
1589
- }
1590
- _closeSession(authenticationToken, deleteSubscriptions, reason) {
1591
- return __awaiter(this, void 0, void 0, function* () {
1592
- if (deleteSubscriptions && this.options.onDeleteMonitoredItem) {
1593
- const session = this.getSession(authenticationToken);
1594
- if (session) {
1595
- const subscriptions = session.publishEngine.subscriptions;
1596
- for (const subscription of subscriptions) {
1597
- yield subscription.applyOnMonitoredItem(this.options.onDeleteMonitoredItem.bind(null, subscription));
1598
- }
1599
- }
1600
- }
1601
- yield this.engine.closeSession(authenticationToken, deleteSubscriptions, reason);
1602
- });
1603
- }
1604
- /**
1605
- * @method _on_CloseSessionRequest
1606
- * @param message
1607
- * @param channel
1608
- * @private
1609
- */
1610
- _on_CloseSessionRequest(message, channel) {
1611
- const request = message.request;
1612
- (0, node_opcua_assert_1.assert)(request instanceof node_opcua_service_session_1.CloseSessionRequest);
1613
- let response;
1614
- message.session_statusCode = node_opcua_status_code_1.StatusCodes.Good;
1615
- function sendError(statusCode) {
1616
- return g_sendError(channel, message, node_opcua_service_session_1.CloseSessionResponse, statusCode);
1617
- }
1618
- function sendResponse(response1) {
1619
- channel.send_response("MSG", response1, message);
1620
- }
1621
- // do not use _apply_on_SessionObject
1622
- // this._apply_on_SessionObject(CloseSessionResponse, message, channel, function (session) {
1623
- // });
1624
- const session = message.session;
1625
- if (!session) {
1626
- return sendError(node_opcua_status_code_1.StatusCodes.BadSessionIdInvalid);
1627
- }
1628
- // session has been created but not activated !
1629
- const wasNotActivated = session.status === "new";
1630
- (() => __awaiter(this, void 0, void 0, function* () {
1631
- yield this._closeSession(request.requestHeader.authenticationToken, request.deleteSubscriptions, "CloseSession");
1632
- // if (false && wasNotActivated) {
1633
- // return sendError(StatusCodes.BadSessionNotActivated);
1634
- // }
1635
- response = new node_opcua_service_session_1.CloseSessionResponse({});
1636
- sendResponse(response);
1637
- }))();
1638
- }
1639
- // browse services
1640
- /**
1641
- * @method _on_BrowseRequest
1642
- * @param message
1643
- * @param channel
1644
- * @private
1645
- */
1646
- _on_BrowseRequest(message, channel) {
1647
- const request = message.request;
1648
- (0, node_opcua_assert_1.assert)(request instanceof node_opcua_service_browse_1.BrowseRequest);
1649
- const diagnostic = {};
1650
- this._apply_on_SessionObject(node_opcua_service_browse_1.BrowseResponse, message, channel, (session, sendResponse, sendError) => {
1651
- let response;
1652
- // test view
1653
- if (request.view && !request.view.viewId.isEmpty()) {
1654
- let theView = this.engine.addressSpace.findNode(request.view.viewId);
1655
- if (theView && theView.nodeClass !== node_opcua_data_model_1.NodeClass.View) {
1656
- // Error: theView is not a View
1657
- diagnostic.localizedText = { text: "Expecting a view here" };
1658
- theView = null;
1659
- }
1660
- if (!theView) {
1661
- return sendError(node_opcua_status_code_1.StatusCodes.BadViewIdUnknown);
1662
- }
1663
- }
1664
- if (!request.nodesToBrowse || request.nodesToBrowse.length === 0) {
1665
- return sendError(node_opcua_status_code_1.StatusCodes.BadNothingToDo);
1666
- }
1667
- if (this.engine.serverCapabilities.operationLimits.maxNodesPerBrowse > 0) {
1668
- if (request.nodesToBrowse.length > this.engine.serverCapabilities.operationLimits.maxNodesPerBrowse) {
1669
- return sendError(node_opcua_status_code_1.StatusCodes.BadTooManyOperations);
1670
- }
1671
- }
1672
- // limit results to requestedMaxReferencesPerNode further so it never exceed a too big number
1673
- const requestedMaxReferencesPerNode = Math.min(9876, request.requestedMaxReferencesPerNode);
1674
- (0, node_opcua_assert_1.assert)(request.nodesToBrowse[0].schema.name === "BrowseDescription");
1675
- const context = new node_opcua_address_space_1.SessionContext({ session, server: this });
1676
- const f = (0, util_1.callbackify)(this.engine.browseWithAutomaticExpansion).bind(this.engine);
1677
- f(request.nodesToBrowse, context, (err, results) => {
1678
- // istanbul ignore next
1679
- if (!results) {
1680
- throw new Error("internal error : " + (err === null || err === void 0 ? void 0 : err.message));
1681
- }
1682
- (0, node_opcua_assert_1.assert)(results[0].schema.name === "BrowseResult");
1683
- // handle continuation point and requestedMaxReferencesPerNode
1684
- const maxBrowseContinuationPoints = this.engine.serverCapabilities.maxBrowseContinuationPoints;
1685
- results = results.map((result) => {
1686
- (0, node_opcua_assert_1.assert)(!result.continuationPoint);
1687
- // istanbul ignore next
1688
- if (!session.continuationPointManager) {
1689
- return new node_opcua_types_1.BrowseResult({ statusCode: node_opcua_status_code_1.StatusCodes.BadNoContinuationPoints });
1690
- }
1691
- if (session.continuationPointManager.hasReachedMaximum(maxBrowseContinuationPoints)) {
1692
- return new node_opcua_types_1.BrowseResult({ statusCode: node_opcua_status_code_1.StatusCodes.BadNoContinuationPoints });
1693
- }
1694
- const truncatedResult = session.continuationPointManager.registerReferences(requestedMaxReferencesPerNode, result.references || [], { continuationPoint: null });
1695
- let { statusCode } = truncatedResult;
1696
- const { continuationPoint, values } = truncatedResult;
1697
- statusCode = result.statusCode;
1698
- return new node_opcua_types_1.BrowseResult({
1699
- statusCode,
1700
- continuationPoint,
1701
- references: values
1702
- });
1703
- });
1704
- response = new node_opcua_service_browse_1.BrowseResponse({
1705
- diagnosticInfos: undefined,
1706
- results
1707
- });
1708
- sendResponse(response);
1709
- });
1710
- });
1711
- }
1712
- /**
1713
- * @method _on_BrowseNextRequest
1714
- * @param message
1715
- * @param channel
1716
- * @private
1717
- */
1718
- _on_BrowseNextRequest(message, channel) {
1719
- const request = message.request;
1720
- (0, node_opcua_assert_1.assert)(request instanceof node_opcua_service_browse_1.BrowseNextRequest);
1721
- this._apply_on_SessionObject(node_opcua_service_browse_1.BrowseNextResponse, message, channel, (session, sendResponse, sendError) => {
1722
- if (!request.continuationPoints || request.continuationPoints.length === 0) {
1723
- return sendError(node_opcua_status_code_1.StatusCodes.BadNothingToDo);
1724
- }
1725
- const results = request.continuationPoints
1726
- .map((continuationPoint, index) => session.continuationPointManager.getNextReferences(0, {
1727
- continuationPoint,
1728
- index,
1729
- releaseContinuationPoints: request.releaseContinuationPoints
1730
- }))
1731
- .map((r) => ({
1732
- continuationPoint: r.continuationPoint,
1733
- references: r.values,
1734
- statusCode: r.statusCode
1735
- }));
1736
- const response = new node_opcua_service_browse_1.BrowseNextResponse({
1737
- diagnosticInfos: undefined,
1738
- results
1739
- });
1740
- sendResponse(response);
1741
- });
1742
- }
1743
- // read services
1744
- _on_ReadRequest(message, channel) {
1745
- const request = message.request;
1746
- (0, node_opcua_assert_1.assert)(request instanceof node_opcua_service_read_1.ReadRequest);
1747
- this._apply_on_SessionObject(node_opcua_service_read_1.ReadResponse, message, channel, (session, sendResponse, sendError) => {
1748
- const context = new node_opcua_address_space_1.SessionContext({ session, server: this });
1749
- let response;
1750
- let results = [];
1751
- const timestampsToReturn = request.timestampsToReturn;
1752
- if (timestampsToReturn === node_opcua_service_read_1.TimestampsToReturn.Invalid) {
1753
- return sendError(node_opcua_status_code_1.StatusCodes.BadTimestampsToReturnInvalid);
1754
- }
1755
- if (request.maxAge < 0) {
1756
- return sendError(node_opcua_status_code_1.StatusCodes.BadMaxAgeInvalid);
1757
- }
1758
- request.nodesToRead = request.nodesToRead || [];
1759
- if (!request.nodesToRead || request.nodesToRead.length <= 0) {
1760
- return sendError(node_opcua_status_code_1.StatusCodes.BadNothingToDo);
1761
- }
1762
- (0, node_opcua_assert_1.assert)(request.nodesToRead[0].schema.name === "ReadValueId");
1763
- // limit size of nodesToRead array to maxNodesPerRead
1764
- if (this.engine.serverCapabilities.operationLimits.maxNodesPerRead > 0) {
1765
- if (request.nodesToRead.length > this.engine.serverCapabilities.operationLimits.maxNodesPerRead) {
1766
- return sendError(node_opcua_status_code_1.StatusCodes.BadTooManyOperations);
1767
- }
1768
- }
1769
- // proceed with registered nodes alias resolution
1770
- for (const nodeToRead of request.nodesToRead) {
1771
- nodeToRead.nodeId = session.resolveRegisteredNode(nodeToRead.nodeId);
1772
- }
1773
- // ask for a refresh of asynchronous variables
1774
- this.engine.refreshValues(request.nodesToRead, request.maxAge, (err) => {
1775
- (0, node_opcua_assert_1.assert)(!err, " error not handled here , fix me");
1776
- results = this.engine.read(context, request);
1777
- (0, node_opcua_assert_1.assert)(results[0].schema.name === "DataValue");
1778
- (0, node_opcua_assert_1.assert)(results.length === request.nodesToRead.length);
1779
- response = new node_opcua_service_read_1.ReadResponse({
1780
- diagnosticInfos: undefined,
1781
- results: undefined
1782
- });
1783
- // set it here for performance
1784
- response.results = results;
1785
- (0, node_opcua_assert_1.assert)(response.diagnosticInfos.length === 0);
1786
- sendResponse(response);
1787
- });
1788
- });
1789
- }
1790
- // read services
1791
- _on_HistoryReadRequest(message, channel) {
1792
- const request = message.request;
1793
- (0, node_opcua_assert_1.assert)(request instanceof node_opcua_service_history_1.HistoryReadRequest);
1794
- this._apply_on_SessionObject(node_opcua_service_history_1.HistoryReadResponse, message, channel, (session, sendResponse, sendError) => {
1795
- let response;
1796
- const timestampsToReturn = request.timestampsToReturn;
1797
- if (timestampsToReturn === node_opcua_service_read_1.TimestampsToReturn.Invalid) {
1798
- return sendError(node_opcua_status_code_1.StatusCodes.BadTimestampsToReturnInvalid);
1799
- }
1800
- request.nodesToRead = request.nodesToRead || [];
1801
- if (!request.nodesToRead || request.nodesToRead.length <= 0) {
1802
- return sendError(node_opcua_status_code_1.StatusCodes.BadNothingToDo);
1803
- }
1804
- (0, node_opcua_assert_1.assert)(request.nodesToRead[0].schema.name === "HistoryReadValueId");
1805
- // limit size of nodesToRead array to maxNodesPerRead
1806
- if (this.engine.serverCapabilities.operationLimits.maxNodesPerRead > 0) {
1807
- if (request.nodesToRead.length > this.engine.serverCapabilities.operationLimits.maxNodesPerRead) {
1808
- return sendError(node_opcua_status_code_1.StatusCodes.BadTooManyOperations);
1809
- }
1810
- }
1811
- // todo : handle
1812
- if (this.engine.serverCapabilities.operationLimits.maxNodesPerHistoryReadData > 0) {
1813
- if (request.nodesToRead.length > this.engine.serverCapabilities.operationLimits.maxNodesPerHistoryReadData) {
1814
- return sendError(node_opcua_status_code_1.StatusCodes.BadTooManyOperations);
1815
- }
1816
- }
1817
- if (this.engine.serverCapabilities.operationLimits.maxNodesPerHistoryReadEvents > 0) {
1818
- if (request.nodesToRead.length > this.engine.serverCapabilities.operationLimits.maxNodesPerHistoryReadEvents) {
1819
- return sendError(node_opcua_status_code_1.StatusCodes.BadTooManyOperations);
1820
- }
1821
- }
1822
- const context = new node_opcua_address_space_1.SessionContext({ session, server: this });
1823
- // ask for a refresh of asynchronous variables
1824
- this.engine.refreshValues(request.nodesToRead, 0, (err) => {
1825
- (0, node_opcua_assert_1.assert)(!err, " error not handled here , fix me"); // TODO
1826
- this.engine.historyRead(context, request, (err1, results) => {
1827
- if (err1) {
1828
- return sendError(node_opcua_status_code_1.StatusCodes.BadHistoryOperationInvalid);
1829
- }
1830
- if (!results) {
1831
- return sendError(node_opcua_status_code_1.StatusCodes.BadHistoryOperationInvalid);
1832
- }
1833
- (0, node_opcua_assert_1.assert)(results[0].schema.name === "HistoryReadResult");
1834
- (0, node_opcua_assert_1.assert)(results.length === request.nodesToRead.length);
1835
- response = new node_opcua_service_history_1.HistoryReadResponse({
1836
- diagnosticInfos: undefined,
1837
- results
1838
- });
1839
- (0, node_opcua_assert_1.assert)(response.diagnosticInfos.length === 0);
1840
- sendResponse(response);
1841
- });
1842
- });
1843
- });
1844
- }
1845
- /*
1846
- // write services
1847
- // OPCUA Specification 1.02 Part 3 : 5.10.4 Write
1848
- // This Service is used to write values to one or more Attributes of one or more Nodes. For constructed
1849
- // Attribute values whose elements are indexed, such as an array, this Service allows Clients to write
1850
- // the entire set of indexed values as a composite, to write individual elements or to write ranges of
1851
- // elements of the composite.
1852
- // The values are written to the data source, such as a device, and the Service does not return until it writes
1853
- // the values or determines that the value cannot be written. In certain cases, the Server will successfully
1854
- // to an intermediate system or Server, and will not know if the data source was updated properly. In these cases,
1855
- // the Server should report a success code that indicates that the write was not verified.
1856
- // In the cases where the Server is able to verify that it has successfully written to the data source,
1857
- // it reports an unconditional success.
1858
- */
1859
- _on_WriteRequest(message, channel) {
1860
- const request = message.request;
1861
- (0, node_opcua_assert_1.assert)(request instanceof node_opcua_service_write_1.WriteRequest);
1862
- (0, node_opcua_assert_1.assert)(!request.nodesToWrite || Array.isArray(request.nodesToWrite));
1863
- this._apply_on_SessionObject(node_opcua_service_write_1.WriteResponse, message, channel, (session, sendResponse, sendError) => {
1864
- let response;
1865
- if (!request.nodesToWrite || request.nodesToWrite.length === 0) {
1866
- return sendError(node_opcua_status_code_1.StatusCodes.BadNothingToDo);
1867
- }
1868
- if (this.engine.serverCapabilities.operationLimits.maxNodesPerWrite > 0) {
1869
- if (request.nodesToWrite.length > this.engine.serverCapabilities.operationLimits.maxNodesPerWrite) {
1870
- return sendError(node_opcua_status_code_1.StatusCodes.BadTooManyOperations);
1871
- }
1872
- }
1873
- // proceed with registered nodes alias resolution
1874
- for (const nodeToWrite of request.nodesToWrite) {
1875
- nodeToWrite.nodeId = session.resolveRegisteredNode(nodeToWrite.nodeId);
1876
- }
1877
- const context = new node_opcua_address_space_1.SessionContext({ session, server: this });
1878
- (0, node_opcua_assert_1.assert)(request.nodesToWrite[0].schema.name === "WriteValue");
1879
- this.engine.write(context, request.nodesToWrite, (err, results) => {
1880
- if (err) {
1881
- errorLog(err);
1882
- return sendError(node_opcua_status_code_1.StatusCodes.BadInternalError);
1883
- }
1884
- (0, node_opcua_assert_1.assert)(Array.isArray(results));
1885
- (0, node_opcua_assert_1.assert)(results.length === request.nodesToWrite.length);
1886
- response = new node_opcua_service_write_1.WriteResponse({
1887
- diagnosticInfos: undefined,
1888
- results
1889
- });
1890
- sendResponse(response);
1891
- });
1892
- });
1893
- }
1894
- // subscription services
1895
- _on_CreateSubscriptionRequest(message, channel) {
1896
- const engine = this.engine;
1897
- const addressSpace = engine.addressSpace;
1898
- const request = message.request;
1899
- (0, node_opcua_assert_1.assert)(request instanceof node_opcua_service_subscription_1.CreateSubscriptionRequest);
1900
- this._apply_on_SessionObject(node_opcua_service_subscription_1.CreateSubscriptionResponse, message, channel, (session, sendResponse, sendError) => {
1901
- const context = new node_opcua_address_space_1.SessionContext({ session, server: this });
1902
- if (session.currentSubscriptionCount >= this.engine.serverCapabilities.maxSubscriptionsPerSession) {
1903
- return sendError(node_opcua_status_code_1.StatusCodes.BadTooManySubscriptions);
1904
- }
1905
- if (this.currentSubscriptionCount >= this.engine.serverCapabilities.maxSubscriptions) {
1906
- return sendError(node_opcua_status_code_1.StatusCodes.BadTooManySubscriptions);
1907
- }
1908
- const subscription = session.createSubscription(request);
1909
- subscription.on("monitoredItem", (monitoredItem) => {
1910
- prepareMonitoredItem(context, addressSpace, monitoredItem);
1911
- });
1912
- const response = new node_opcua_service_subscription_1.CreateSubscriptionResponse({
1913
- revisedLifetimeCount: subscription.lifeTimeCount,
1914
- revisedMaxKeepAliveCount: subscription.maxKeepAliveCount,
1915
- revisedPublishingInterval: subscription.publishingInterval,
1916
- subscriptionId: subscription.id
1917
- });
1918
- sendResponse(response);
1919
- });
1920
- }
1921
- _on_DeleteSubscriptionsRequest(message, channel) {
1922
- const request = message.request;
1923
- (0, node_opcua_assert_1.assert)(request instanceof node_opcua_service_subscription_1.DeleteSubscriptionsRequest);
1924
- this._apply_on_SubscriptionIds(node_opcua_service_subscription_1.DeleteSubscriptionsResponse, message, channel, (session, subscriptionId) => __awaiter(this, void 0, void 0, function* () {
1925
- let subscription = this.engine.findOrphanSubscription(subscriptionId);
1926
- // istanbul ignore next
1927
- if (subscription) {
1928
- warningLog("Deleting an orphan subscription", subscriptionId);
1929
- yield this._beforeDeleteSubscription(subscription);
1930
- return this.engine.deleteOrphanSubscription(subscription);
1931
- }
1932
- subscription = session.getSubscription(subscriptionId);
1933
- if (subscription) {
1934
- yield this._beforeDeleteSubscription(subscription);
1935
- }
1936
- return session.deleteSubscription(subscriptionId);
1937
- }));
1938
- }
1939
- _on_TransferSubscriptionsRequest(message, channel) {
1940
- //
1941
- // sendInitialValue Boolean
1942
- // A Boolean parameter with the following values:
1943
- // TRUE the first Publish response(s) after the TransferSubscriptions call shall
1944
- // contain the current values of all Monitored Items in the Subscription where
1945
- // the Monitoring Mode is set to Reporting.
1946
- // FALSE the first Publish response after the TransferSubscriptions call shall contain only the value
1947
- // changes since the last Publish response was sent.
1948
- // This parameter only applies to MonitoredItems used for monitoring Attribute changes.
1949
- //
1950
- const engine = this.engine;
1951
- const request = message.request;
1952
- (0, node_opcua_assert_1.assert)(request instanceof node_opcua_service_subscription_1.TransferSubscriptionsRequest);
1953
- this._apply_on_SubscriptionIds(node_opcua_service_subscription_1.TransferSubscriptionsResponse, message, channel, (session, subscriptionId) => __awaiter(this, void 0, void 0, function* () { return yield engine.transferSubscription(session, subscriptionId, request.sendInitialValues); }));
1954
- }
1955
- _on_CreateMonitoredItemsRequest(message, channel) {
1956
- const engine = this.engine;
1957
- const addressSpace = engine.addressSpace;
1958
- const request = message.request;
1959
- (0, node_opcua_assert_1.assert)(request instanceof node_opcua_service_subscription_1.CreateMonitoredItemsRequest);
1960
- this._apply_on_Subscription(node_opcua_service_subscription_1.CreateMonitoredItemsResponse, message, channel, (session, subscription, sendResponse, sendError) => __awaiter(this, void 0, void 0, function* () {
1961
- const timestampsToReturn = request.timestampsToReturn;
1962
- if (timestampsToReturn === node_opcua_service_read_1.TimestampsToReturn.Invalid) {
1963
- return sendError(node_opcua_status_code_1.StatusCodes.BadTimestampsToReturnInvalid);
1964
- }
1965
- if (!request.itemsToCreate || request.itemsToCreate.length === 0) {
1966
- return sendError(node_opcua_status_code_1.StatusCodes.BadNothingToDo);
1967
- }
1968
- if (this.engine.serverCapabilities.operationLimits.maxMonitoredItemsPerCall > 0) {
1969
- if (request.itemsToCreate.length > this.engine.serverCapabilities.operationLimits.maxMonitoredItemsPerCall) {
1970
- return sendError(node_opcua_status_code_1.StatusCodes.BadTooManyOperations);
1971
- }
1972
- }
1973
- const options = this.options;
1974
- let results = [];
1975
- if (options.onCreateMonitoredItem) {
1976
- const resultsPromise = request.itemsToCreate.map((monitoredItemCreateRequest) => __awaiter(this, void 0, void 0, function* () {
1977
- const { monitoredItem, createResult } = subscription.preCreateMonitoredItem(addressSpace, timestampsToReturn, monitoredItemCreateRequest);
1978
- if (monitoredItem) {
1979
- yield options.onCreateMonitoredItem(subscription, monitoredItem);
1980
- subscription.postCreateMonitoredItem(monitoredItem, monitoredItemCreateRequest, createResult);
1981
- }
1982
- return createResult;
1983
- }));
1984
- results = yield Promise.all(resultsPromise);
1985
- }
1986
- else {
1987
- results = request.itemsToCreate.map((monitoredItemCreateRequest) => {
1988
- const { monitoredItem, createResult } = subscription.preCreateMonitoredItem(addressSpace, timestampsToReturn, monitoredItemCreateRequest);
1989
- if (monitoredItem) {
1990
- subscription.postCreateMonitoredItem(monitoredItem, monitoredItemCreateRequest, createResult);
1991
- }
1992
- return createResult;
1993
- });
1994
- }
1995
- const response = new node_opcua_service_subscription_1.CreateMonitoredItemsResponse({
1996
- responseHeader: { serviceResult: node_opcua_status_code_1.StatusCodes.Good },
1997
- results
1998
- // ,diagnosticInfos: []
1999
- });
2000
- sendResponse(response);
2001
- }));
2002
- }
2003
- _on_ModifySubscriptionRequest(message, channel) {
2004
- const request = message.request;
2005
- (0, node_opcua_assert_1.assert)(request instanceof node_opcua_service_subscription_1.ModifySubscriptionRequest);
2006
- this._apply_on_Subscription(node_opcua_service_subscription_1.ModifySubscriptionResponse, message, channel, (session, subscription, sendResponse, sendError) => __awaiter(this, void 0, void 0, function* () {
2007
- subscription.modify(request);
2008
- const response = new node_opcua_service_subscription_1.ModifySubscriptionResponse({
2009
- revisedLifetimeCount: subscription.lifeTimeCount,
2010
- revisedMaxKeepAliveCount: subscription.maxKeepAliveCount,
2011
- revisedPublishingInterval: subscription.publishingInterval
2012
- });
2013
- sendResponse(response);
2014
- }));
2015
- }
2016
- _on_ModifyMonitoredItemsRequest(message, channel) {
2017
- const request = message.request;
2018
- (0, node_opcua_assert_1.assert)(request instanceof node_opcua_service_subscription_1.ModifyMonitoredItemsRequest);
2019
- this._apply_on_Subscription(node_opcua_service_subscription_1.ModifyMonitoredItemsResponse, message, channel, (session, subscription, sendResponse, sendError) => __awaiter(this, void 0, void 0, function* () {
2020
- const timestampsToReturn = request.timestampsToReturn;
2021
- if (timestampsToReturn === node_opcua_service_read_1.TimestampsToReturn.Invalid) {
2022
- return sendError(node_opcua_status_code_1.StatusCodes.BadTimestampsToReturnInvalid);
2023
- }
2024
- if (!request.itemsToModify || request.itemsToModify.length === 0) {
2025
- return sendError(node_opcua_status_code_1.StatusCodes.BadNothingToDo);
2026
- }
2027
- /* istanbul ignore next */
2028
- if (this.engine.serverCapabilities.operationLimits.maxMonitoredItemsPerCall > 0) {
2029
- if (request.itemsToModify.length > this.engine.serverCapabilities.operationLimits.maxMonitoredItemsPerCall) {
2030
- return sendError(node_opcua_status_code_1.StatusCodes.BadTooManyOperations);
2031
- }
2032
- }
2033
- const itemsToModify = request.itemsToModify; // MonitoredItemModifyRequest
2034
- function modifyMonitoredItem(item) {
2035
- const monitoredItemId = item.monitoredItemId;
2036
- const monitoredItem = subscription.getMonitoredItem(monitoredItemId);
2037
- if (!monitoredItem) {
2038
- return new node_opcua_service_subscription_1.MonitoredItemModifyResult({ statusCode: node_opcua_status_code_1.StatusCodes.BadMonitoredItemIdInvalid });
2039
- }
2040
- // adjust samplingInterval if === -1
2041
- if (item.requestedParameters.samplingInterval === -1) {
2042
- item.requestedParameters.samplingInterval = subscription.publishingInterval;
2043
- }
2044
- return monitoredItem.modify(timestampsToReturn, item.requestedParameters);
2045
- }
2046
- const results = itemsToModify.map(modifyMonitoredItem);
2047
- const response = new node_opcua_service_subscription_1.ModifyMonitoredItemsResponse({
2048
- results
2049
- });
2050
- sendResponse(response);
2051
- }));
2052
- }
2053
- _on_PublishRequest(message, channel) {
2054
- const request = message.request;
2055
- (0, node_opcua_assert_1.assert)(request instanceof node_opcua_service_subscription_1.PublishRequest);
2056
- this._apply_on_SessionObject(node_opcua_service_subscription_1.PublishResponse, message, channel, (session, sendResponse, sendError) => {
2057
- (0, node_opcua_assert_1.assert)(session);
2058
- (0, node_opcua_assert_1.assert)(session.publishEngine); // server.publishEngine doesn't exists, OPCUAServer has probably shut down already
2059
- session.publishEngine._on_PublishRequest(request, (_request1, response) => {
2060
- sendResponse(response);
2061
- });
2062
- });
2063
- }
2064
- _on_SetPublishingModeRequest(message, channel) {
2065
- const request = message.request;
2066
- (0, node_opcua_assert_1.assert)(request instanceof node_opcua_service_subscription_1.SetPublishingModeRequest);
2067
- const publishingEnabled = request.publishingEnabled;
2068
- this._apply_on_Subscriptions(node_opcua_service_subscription_1.SetPublishingModeResponse, message, channel, (session, subscription) => __awaiter(this, void 0, void 0, function* () {
2069
- return subscription.setPublishingMode(publishingEnabled);
2070
- }));
2071
- }
2072
- _on_DeleteMonitoredItemsRequest(message, channel) {
2073
- const request = message.request;
2074
- (0, node_opcua_assert_1.assert)(request instanceof node_opcua_service_subscription_1.DeleteMonitoredItemsRequest);
2075
- this._apply_on_Subscription(node_opcua_service_subscription_1.DeleteMonitoredItemsResponse, message, channel, (session, subscription, sendResponse, sendError) => __awaiter(this, void 0, void 0, function* () {
2076
- /* istanbul ignore next */
2077
- if (!request.monitoredItemIds || request.monitoredItemIds.length === 0) {
2078
- return sendError(node_opcua_status_code_1.StatusCodes.BadNothingToDo);
2079
- }
2080
- /* istanbul ignore next */
2081
- if (this.engine.serverCapabilities.operationLimits.maxMonitoredItemsPerCall > 0) {
2082
- if (request.monitoredItemIds.length > this.engine.serverCapabilities.operationLimits.maxMonitoredItemsPerCall) {
2083
- return sendError(node_opcua_status_code_1.StatusCodes.BadTooManyOperations);
2084
- }
2085
- }
2086
- const resultsPromises = request.monitoredItemIds.map((monitoredItemId) => __awaiter(this, void 0, void 0, function* () {
2087
- if (this.options.onDeleteMonitoredItem) {
2088
- const monitoredItem = subscription.getMonitoredItem(monitoredItemId);
2089
- if (monitoredItem) {
2090
- yield this.options.onDeleteMonitoredItem(subscription, monitoredItem);
2091
- }
2092
- }
2093
- return subscription.removeMonitoredItem(monitoredItemId);
2094
- }));
2095
- try {
2096
- const results = yield Promise.all(resultsPromises);
2097
- const response = new node_opcua_service_subscription_1.DeleteMonitoredItemsResponse({
2098
- diagnosticInfos: undefined,
2099
- results
2100
- });
2101
- sendResponse(response);
2102
- }
2103
- catch (err) {
2104
- warningLog(err);
2105
- return sendError(node_opcua_status_code_1.StatusCodes.BadInternalError);
2106
- }
2107
- }));
2108
- }
2109
- _on_SetTriggeringRequest(message, channel) {
2110
- const request = message.request;
2111
- (0, node_opcua_assert_1.assert)(request instanceof node_opcua_service_subscription_1.SetTriggeringRequest);
2112
- this._apply_on_Subscription(node_opcua_service_subscription_1.SetTriggeringResponse, message, channel, (session, subscription, sendResponse, sendError) => __awaiter(this, void 0, void 0, function* () {
2113
- /* */
2114
- const { triggeringItemId, linksToAdd, linksToRemove } = request;
2115
- /**
2116
- * The MaxMonitoredItemsPerCall Property indicates
2117
- * [...]
2118
- * • the maximum size of the sum of the linksToAdd and linksToRemove arrays when a
2119
- * Client calls the SetTriggering Service.
2120
- *
2121
- */
2122
- const maxElements = (linksToAdd ? linksToAdd.length : 0) + (linksToRemove ? linksToRemove.length : 0);
2123
- if (this.engine.serverCapabilities.operationLimits.maxMonitoredItemsPerCall > 0) {
2124
- if (maxElements > this.engine.serverCapabilities.operationLimits.maxMonitoredItemsPerCall) {
2125
- return sendError(node_opcua_status_code_1.StatusCodes.BadTooManyOperations);
2126
- }
2127
- }
2128
- const { addResults, removeResults, statusCode } = subscription.setTriggering(triggeringItemId, linksToAdd, linksToRemove);
2129
- if (statusCode !== node_opcua_status_code_1.StatusCodes.Good) {
2130
- const response = new node_opcua_types_1.ServiceFault({ responseHeader: { serviceResult: statusCode } });
2131
- sendResponse(response);
2132
- }
2133
- else {
2134
- const response = new node_opcua_service_subscription_1.SetTriggeringResponse({
2135
- responseHeader: { serviceResult: statusCode },
2136
- addResults,
2137
- removeResults,
2138
- addDiagnosticInfos: null,
2139
- removeDiagnosticInfos: null
2140
- });
2141
- sendResponse(response);
2142
- }
2143
- }));
2144
- }
2145
- _beforeDeleteSubscription(subscription) {
2146
- return __awaiter(this, void 0, void 0, function* () {
2147
- if (!this.options.onDeleteMonitoredItem) {
2148
- return;
2149
- }
2150
- yield subscription.applyOnMonitoredItem(this.options.onDeleteMonitoredItem.bind(null, subscription));
2151
- });
2152
- }
2153
- _on_RepublishRequest(message, channel) {
2154
- const request = message.request;
2155
- (0, node_opcua_assert_1.assert)(request instanceof node_opcua_service_subscription_1.RepublishRequest);
2156
- this._apply_on_Subscription(node_opcua_service_subscription_1.RepublishResponse, message, channel, (session, subscription, sendResponse, sendError) => __awaiter(this, void 0, void 0, function* () {
2157
- // update diagnostic counter
2158
- subscription.subscriptionDiagnostics.republishRequestCount += 1;
2159
- subscription.subscriptionDiagnostics.republishMessageRequestCount += 1;
2160
- const retransmitSequenceNumber = request.retransmitSequenceNumber;
2161
- const notificationMessage = subscription.getMessageForSequenceNumber(retransmitSequenceNumber);
2162
- if (!notificationMessage) {
2163
- return sendError(node_opcua_status_code_1.StatusCodes.BadMessageNotAvailable);
2164
- }
2165
- const response = new node_opcua_service_subscription_1.RepublishResponse({
2166
- notificationMessage,
2167
- responseHeader: {
2168
- serviceResult: node_opcua_status_code_1.StatusCodes.Good
2169
- }
2170
- });
2171
- // update diagnostic counter
2172
- subscription.subscriptionDiagnostics.republishMessageCount += 1;
2173
- sendResponse(response);
2174
- }));
2175
- }
2176
- // Bad_NothingToDo
2177
- // Bad_TooManyOperations
2178
- // Bad_SubscriptionIdInvalid
2179
- // Bad_MonitoringModeInvalid
2180
- _on_SetMonitoringModeRequest(message, channel) {
2181
- const request = message.request;
2182
- (0, node_opcua_assert_1.assert)(request instanceof node_opcua_service_subscription_1.SetMonitoringModeRequest);
2183
- this._apply_on_Subscription(node_opcua_service_subscription_1.SetMonitoringModeResponse, message, channel, (session, subscription, sendResponse, sendError) => __awaiter(this, void 0, void 0, function* () {
2184
- /* istanbul ignore next */
2185
- if (!request.monitoredItemIds || request.monitoredItemIds.length === 0) {
2186
- return sendError(node_opcua_status_code_1.StatusCodes.BadNothingToDo);
2187
- }
2188
- /* istanbul ignore next */
2189
- if (this.engine.serverCapabilities.operationLimits.maxMonitoredItemsPerCall > 0) {
2190
- if (request.monitoredItemIds.length > this.engine.serverCapabilities.operationLimits.maxMonitoredItemsPerCall) {
2191
- return sendError(node_opcua_status_code_1.StatusCodes.BadTooManyOperations);
2192
- }
2193
- }
2194
- const monitoringMode = request.monitoringMode;
2195
- if (!isMonitoringModeValid(monitoringMode)) {
2196
- return sendError(node_opcua_status_code_1.StatusCodes.BadMonitoringModeInvalid);
2197
- }
2198
- const results = request.monitoredItemIds.map((monitoredItemId) => {
2199
- const monitoredItem = subscription.getMonitoredItem(monitoredItemId);
2200
- if (!monitoredItem) {
2201
- return node_opcua_status_code_1.StatusCodes.BadMonitoredItemIdInvalid;
2202
- }
2203
- monitoredItem.setMonitoringMode(monitoringMode);
2204
- return node_opcua_status_code_1.StatusCodes.Good;
2205
- });
2206
- const response = new node_opcua_service_subscription_1.SetMonitoringModeResponse({
2207
- results
2208
- });
2209
- sendResponse(response);
2210
- }));
2211
- }
2212
- // _on_TranslateBrowsePathsToNodeIds service
2213
- _on_TranslateBrowsePathsToNodeIdsRequest(message, channel) {
2214
- const request = message.request;
2215
- (0, node_opcua_assert_1.assert)(request instanceof node_opcua_service_translate_browse_path_1.TranslateBrowsePathsToNodeIdsRequest);
2216
- this._apply_on_SessionObject(node_opcua_service_translate_browse_path_1.TranslateBrowsePathsToNodeIdsResponse, message, channel, (session, sendResponse, sendError) => __awaiter(this, void 0, void 0, function* () {
2217
- if (!request.browsePaths || request.browsePaths.length === 0) {
2218
- return sendError(node_opcua_status_code_1.StatusCodes.BadNothingToDo);
2219
- }
2220
- if (this.engine.serverCapabilities.operationLimits.maxNodesPerTranslateBrowsePathsToNodeIds > 0) {
2221
- if (request.browsePaths.length >
2222
- this.engine.serverCapabilities.operationLimits.maxNodesPerTranslateBrowsePathsToNodeIds) {
2223
- return sendError(node_opcua_status_code_1.StatusCodes.BadTooManyOperations);
2224
- }
2225
- }
2226
- const browsePathsResults = request.browsePaths.map((browsePath) => this.engine.browsePath(browsePath));
2227
- const response = new node_opcua_service_translate_browse_path_1.TranslateBrowsePathsToNodeIdsResponse({
2228
- diagnosticInfos: null,
2229
- results: browsePathsResults
2230
- });
2231
- sendResponse(response);
2232
- }));
2233
- }
2234
- // Call Service Result Codes
2235
- // Symbolic Id Description
2236
- // Bad_NothingToDo See Table 165 for the description of this result code.
2237
- // Bad_TooManyOperations See Table 165 for the description of this result code.
2238
- //
2239
- _on_CallRequest(message, channel) {
2240
- const request = message.request;
2241
- (0, node_opcua_assert_1.assert)(request instanceof node_opcua_service_call_1.CallRequest);
2242
- this._apply_on_SessionObject(node_opcua_service_call_1.CallResponse, message, channel, (session, sendResponse, sendError) => {
2243
- let response;
2244
- if (!request.methodsToCall || request.methodsToCall.length === 0) {
2245
- return sendError(node_opcua_status_code_1.StatusCodes.BadNothingToDo);
2246
- }
2247
- // the MaxNodesPerMethodCall Property indicates the maximum size of the methodsToCall array when
2248
- // a Client calls the Call Service.
2249
- let maxNodesPerMethodCall = this.engine.serverCapabilities.operationLimits.maxNodesPerMethodCall;
2250
- maxNodesPerMethodCall = maxNodesPerMethodCall <= 0 ? 1000 : maxNodesPerMethodCall;
2251
- if (request.methodsToCall.length > maxNodesPerMethodCall) {
2252
- return sendError(node_opcua_status_code_1.StatusCodes.BadTooManyOperations);
2253
- }
2254
- /* jshint validthis: true */
2255
- const addressSpace = this.engine.addressSpace;
2256
- const context = new node_opcua_address_space_1.SessionContext({ session, server: this });
2257
- async.map(request.methodsToCall, node_opcua_address_space_1.callMethodHelper.bind(null, context, addressSpace), (err, results) => {
2258
- /* istanbul ignore next */
2259
- if (err) {
2260
- errorLog("ERROR in method Call !! ", err);
2261
- }
2262
- (0, node_opcua_assert_1.assert)(Array.isArray(results));
2263
- response = new node_opcua_service_call_1.CallResponse({
2264
- results: results
2265
- });
2266
- filterDiagnosticInfo(request.requestHeader.returnDiagnostics, response);
2267
- sendResponse(response);
2268
- });
2269
- });
2270
- }
2271
- _on_RegisterNodesRequest(message, channel) {
2272
- const request = message.request;
2273
- (0, node_opcua_assert_1.assert)(request instanceof node_opcua_service_register_node_1.RegisterNodesRequest);
2274
- this._apply_on_SessionObject(node_opcua_service_register_node_1.RegisterNodesResponse, message, channel, (session, sendResponse, sendError) => {
2275
- if (!request.nodesToRegister || request.nodesToRegister.length === 0) {
2276
- return sendError(node_opcua_status_code_1.StatusCodes.BadNothingToDo);
2277
- }
2278
- if (this.engine.serverCapabilities.operationLimits.maxNodesPerRegisterNodes > 0) {
2279
- if (request.nodesToRegister.length > this.engine.serverCapabilities.operationLimits.maxNodesPerRegisterNodes) {
2280
- return sendError(node_opcua_status_code_1.StatusCodes.BadTooManyOperations);
2281
- }
2282
- }
2283
- // A list of NodeIds which the Client shall use for subsequent access operations. The
2284
- // size and order of this list matches the size and order of the nodesToRegister
2285
- // request parameter.
2286
- // The Server may return the NodeId from the request or a new (an alias) NodeId. It
2287
- // is recommended that the Server return a numeric NodeIds for aliasing.
2288
- // In case no optimization is supported for a Node, the Server shall return the
2289
- // NodeId from the request.
2290
- const registeredNodeIds = request.nodesToRegister.map((nodeId) => session.registerNode(nodeId));
2291
- const response = new node_opcua_service_register_node_1.RegisterNodesResponse({
2292
- registeredNodeIds
2293
- });
2294
- sendResponse(response);
2295
- });
2296
- }
2297
- _on_UnregisterNodesRequest(message, channel) {
2298
- const request = message.request;
2299
- (0, node_opcua_assert_1.assert)(request instanceof node_opcua_service_register_node_1.UnregisterNodesRequest);
2300
- this._apply_on_SessionObject(node_opcua_service_register_node_1.UnregisterNodesResponse, message, channel, (session, sendResponse, sendError) => {
2301
- request.nodesToUnregister = request.nodesToUnregister || [];
2302
- if (!request.nodesToUnregister || request.nodesToUnregister.length === 0) {
2303
- return sendError(node_opcua_status_code_1.StatusCodes.BadNothingToDo);
2304
- }
2305
- if (this.engine.serverCapabilities.operationLimits.maxNodesPerRegisterNodes > 0) {
2306
- if (request.nodesToUnregister.length > this.engine.serverCapabilities.operationLimits.maxNodesPerRegisterNodes) {
2307
- return sendError(node_opcua_status_code_1.StatusCodes.BadTooManyOperations);
2308
- }
2309
- }
2310
- request.nodesToUnregister.map((nodeId) => session.unRegisterNode(nodeId));
2311
- const response = new node_opcua_service_register_node_1.UnregisterNodesResponse({});
2312
- sendResponse(response);
2313
- });
2314
- }
2315
- /* istanbul ignore next */
2316
- _on_Cancel(message, channel) {
2317
- return g_sendError(channel, message, node_opcua_types_1.CancelResponse, node_opcua_status_code_1.StatusCodes.BadServiceUnsupported);
2318
- }
2319
- // NodeManagement Service Set Overview
2320
- // This Service Set defines Services to add and delete AddressSpace Nodes and References between them. All added
2321
- // Nodes continue to exist in the AddressSpace even if the Client that created them disconnects from the Server.
2322
- //
2323
- /* istanbul ignore next */
2324
- _on_AddNodes(message, channel) {
2325
- return g_sendError(channel, message, node_opcua_service_node_management_1.AddNodesResponse, node_opcua_status_code_1.StatusCodes.BadServiceUnsupported);
2326
- }
2327
- /* istanbul ignore next */
2328
- _on_AddReferences(message, channel) {
2329
- return g_sendError(channel, message, node_opcua_service_node_management_1.AddReferencesResponse, node_opcua_status_code_1.StatusCodes.BadServiceUnsupported);
2330
- }
2331
- /* istanbul ignore next */
2332
- _on_DeleteNodes(message, channel) {
2333
- return g_sendError(channel, message, node_opcua_service_node_management_1.DeleteNodesResponse, node_opcua_status_code_1.StatusCodes.BadServiceUnsupported);
2334
- }
2335
- /* istanbul ignore next */
2336
- _on_DeleteReferences(message, channel) {
2337
- return g_sendError(channel, message, node_opcua_service_node_management_1.DeleteReferencesResponse, node_opcua_status_code_1.StatusCodes.BadServiceUnsupported);
2338
- }
2339
- // Query Service
2340
- /* istanbul ignore next */
2341
- _on_QueryFirst(message, channel) {
2342
- return g_sendError(channel, message, node_opcua_service_query_1.QueryFirstResponse, node_opcua_status_code_1.StatusCodes.BadServiceUnsupported);
2343
- }
2344
- /* istanbul ignore next */
2345
- _on_QueryNext(message, channel) {
2346
- return g_sendError(channel, message, node_opcua_service_query_1.QueryNextResponse, node_opcua_status_code_1.StatusCodes.BadServiceUnsupported);
2347
- }
2348
- /* istanbul ignore next */
2349
- _on_HistoryUpdate(message, channel) {
2350
- return g_sendError(channel, message, node_opcua_service_history_1.HistoryUpdateResponse, node_opcua_status_code_1.StatusCodes.BadServiceUnsupported);
2351
- }
2352
- createEndpoint(port1, serverOptions) {
2353
- // add the tcp/ip endpoint with no security
2354
- const endPoint = new server_end_point_1.OPCUAServerEndPoint({
2355
- port: port1,
2356
- certificateManager: this.serverCertificateManager,
2357
- certificateChain: this.getCertificateChain(),
2358
- privateKey: this.getPrivateKey(),
2359
- defaultSecureTokenLifetime: serverOptions.defaultSecureTokenLifetime || 600000,
2360
- timeout: serverOptions.timeout || 3 * 60 * 1000,
2361
- maxConnections: this.maxConnectionsPerEndpoint,
2362
- objectFactory: this.objectFactory,
2363
- serverInfo: this.serverInfo
2364
- });
2365
- return endPoint;
2366
- }
2367
- createEndpointDescriptions(serverOption, endpointOptions) {
2368
- /* istanbul ignore next */
2369
- if (!endpointOptions) {
2370
- throw new Error("internal error");
2371
- }
2372
- const hostname = (0, node_opcua_hostname_1.getFullyQualifiedDomainName)();
2373
- endpointOptions.hostname = endpointOptions.hostname || hostname;
2374
- endpointOptions.port = endpointOptions.port || 26543;
2375
- /* istanbul ignore next */
2376
- if (!Object.prototype.hasOwnProperty.call(endpointOptions, "port") ||
2377
- !isFinite(endpointOptions.port) ||
2378
- typeof endpointOptions.port !== "number") {
2379
- throw new Error("expecting a valid port (number)");
2380
- }
2381
- const port = Number(endpointOptions.port || 0);
2382
- const endPoint = this.createEndpoint(port, serverOption);
2383
- endpointOptions.alternateHostname = endpointOptions.alternateHostname || [];
2384
- const alternateHostname = endpointOptions.alternateHostname instanceof Array
2385
- ? endpointOptions.alternateHostname
2386
- : [endpointOptions.alternateHostname];
2387
- const allowAnonymous = endpointOptions.allowAnonymous === undefined ? true : !!endpointOptions.allowAnonymous;
2388
- endPoint.addStandardEndpointDescriptions({
2389
- allowAnonymous,
2390
- securityModes: endpointOptions.securityModes,
2391
- securityPolicies: endpointOptions.securityPolicies,
2392
- hostname: endpointOptions.hostname,
2393
- alternateHostname,
2394
- disableDiscovery: !!endpointOptions.disableDiscovery,
2395
- // xx hostname,
2396
- resourcePath: serverOption.resourcePath || ""
2397
- });
2398
- return endPoint;
2399
- }
2400
- initializeCM() {
2401
- const _super = Object.create(null, {
2402
- initializeCM: { get: () => super.initializeCM }
2403
- });
2404
- return __awaiter(this, void 0, void 0, function* () {
2405
- yield _super.initializeCM.call(this);
2406
- yield this.userCertificateManager.initialize();
2407
- });
2408
- }
2409
- }
2410
- exports.OPCUAServer = OPCUAServer;
2411
- OPCUAServer.defaultShutdownTimeout = 100; // 250 ms
2412
- /**
2413
- * if requestExactEndpointUrl is set to true the server will only accept createSession that have a endpointUrl that strictly matches
2414
- * one of the provided endpoint.
2415
- * This mean that if the server expose a endpoint with url such as opc.tcp://MYHOSTNAME:1234, client will not be able to reach the server
2416
- * with the ip address of the server.
2417
- * requestExactEndpointUrl = true => emulates the Prosys Server behavior
2418
- * requestExactEndpointUrl = false => emulates the Unified Automation behavior.
2419
- */
2420
- OPCUAServer.requestExactEndpointUrl = g_requestExactEndpointUrl;
2421
- OPCUAServer.registry = new node_opcua_object_registry_1.ObjectRegistry();
2422
- OPCUAServer.fallbackSessionName = "Client didn't provide a meaningful sessionName ...";
2423
- /**
2424
- * the maximum number of subscription that can be created per server
2425
- * @deprecated
2426
- */
2427
- OPCUAServer.deprectated_MAX_SUBSCRIPTION = 50;
2428
- const opts = { multiArgs: false };
2429
- OPCUAServer.prototype.start = thenify.withCallback(OPCUAServer.prototype.start, opts);
2430
- OPCUAServer.prototype.initialize = thenify.withCallback(OPCUAServer.prototype.initialize, opts);
2431
- OPCUAServer.prototype.shutdown = thenify.withCallback(OPCUAServer.prototype.shutdown, opts);
1
+ "use strict";
2
+ /* eslint-disable complexity */
3
+ /**
4
+ * @module node-opcua-server
5
+ */
6
+ // tslint:disable:no-console
7
+ // tslint:disable:max-line-length
8
+ // tslint:disable:unified-signatures
9
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
10
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
11
+ return new (P || (P = Promise))(function (resolve, reject) {
12
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
13
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
14
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
15
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
16
+ });
17
+ };
18
+ Object.defineProperty(exports, "__esModule", { value: true });
19
+ exports.OPCUAServer = exports.RegisterServerMethod = exports.filterDiagnosticInfo = void 0;
20
+ const crypto = require("crypto");
21
+ const util_1 = require("util");
22
+ const async = require("async");
23
+ const chalk = require("chalk");
24
+ const node_opcua_hostname_1 = require("node-opcua-hostname");
25
+ const node_opcua_assert_1 = require("node-opcua-assert");
26
+ const utils = require("node-opcua-utils");
27
+ const node_opcua_address_space_1 = require("node-opcua-address-space");
28
+ const node_opcua_certificate_manager_1 = require("node-opcua-certificate-manager");
29
+ const node_opcua_common_1 = require("node-opcua-common");
30
+ const node_opcua_crypto_1 = require("node-opcua-crypto");
31
+ const node_opcua_data_model_1 = require("node-opcua-data-model");
32
+ const node_opcua_data_value_1 = require("node-opcua-data-value");
33
+ const node_opcua_debug_1 = require("node-opcua-debug");
34
+ const node_opcua_object_registry_1 = require("node-opcua-object-registry");
35
+ const node_opcua_secure_channel_1 = require("node-opcua-secure-channel");
36
+ const node_opcua_service_browse_1 = require("node-opcua-service-browse");
37
+ const node_opcua_service_call_1 = require("node-opcua-service-call");
38
+ const node_opcua_service_endpoints_1 = require("node-opcua-service-endpoints");
39
+ const node_opcua_service_history_1 = require("node-opcua-service-history");
40
+ const node_opcua_service_node_management_1 = require("node-opcua-service-node-management");
41
+ const node_opcua_service_query_1 = require("node-opcua-service-query");
42
+ const node_opcua_service_read_1 = require("node-opcua-service-read");
43
+ const node_opcua_service_register_node_1 = require("node-opcua-service-register-node");
44
+ const node_opcua_service_session_1 = require("node-opcua-service-session");
45
+ const node_opcua_service_subscription_1 = require("node-opcua-service-subscription");
46
+ const node_opcua_service_translate_browse_path_1 = require("node-opcua-service-translate-browse-path");
47
+ const node_opcua_service_write_1 = require("node-opcua-service-write");
48
+ const node_opcua_status_code_1 = require("node-opcua-status-code");
49
+ const node_opcua_types_1 = require("node-opcua-types");
50
+ const node_opcua_variant_1 = require("node-opcua-variant");
51
+ const node_opcua_variant_2 = require("node-opcua-variant");
52
+ const node_opcua_utils_1 = require("node-opcua-utils");
53
+ const base_server_1 = require("./base_server");
54
+ const factory_1 = require("./factory");
55
+ const monitored_item_1 = require("./monitored_item");
56
+ const register_server_manager_1 = require("./register_server_manager");
57
+ const register_server_manager_hidden_1 = require("./register_server_manager_hidden");
58
+ const register_server_manager_mdns_only_1 = require("./register_server_manager_mdns_only");
59
+ const server_end_point_1 = require("./server_end_point");
60
+ const server_engine_1 = require("./server_engine");
61
+ const user_manager_1 = require("./user_manager");
62
+ const user_manager_ua_1 = require("./user_manager_ua");
63
+ function isSubscriptionIdInvalid(subscriptionId) {
64
+ return subscriptionId < 0 || subscriptionId >= 0xffffffff;
65
+ }
66
+ // tslint:disable-next-line:no-var-requires
67
+ const thenify = require("thenify");
68
+ // tslint:disable-next-line:no-var-requires
69
+ const package_info = require("../package.json");
70
+ const debugLog = (0, node_opcua_debug_1.make_debugLog)(__filename);
71
+ const errorLog = (0, node_opcua_debug_1.make_errorLog)(__filename);
72
+ const warningLog = (0, node_opcua_debug_1.make_warningLog)(__filename);
73
+ const default_maxConnectionsPerEndpoint = 10;
74
+ function g_sendError(channel, message, ResponseClass, statusCode) {
75
+ const response = new node_opcua_types_1.ServiceFault({
76
+ responseHeader: { serviceResult: statusCode }
77
+ });
78
+ return channel.send_response("MSG", response, message);
79
+ }
80
+ const default_build_info = {
81
+ manufacturerName: "NodeOPCUA : MIT Licence ( see http://node-opcua.github.io/)",
82
+ productName: "NodeOPCUA-Server",
83
+ productUri: null,
84
+ softwareVersion: package_info.version,
85
+ buildNumber: "0",
86
+ buildDate: new Date(2020, 1, 1)
87
+ // xx buildDate: fs.statSync(package_json_file).mtime
88
+ };
89
+ const minSessionTimeout = 100; // 100 milliseconds
90
+ const defaultSessionTimeout = 1000 * 30; // 30 seconds
91
+ const maxSessionTimeout = 1000 * 60 * 50; // 50 minutes
92
+ let unnamed_session_count = 0;
93
+ function _adjust_session_timeout(sessionTimeout) {
94
+ let revisedSessionTimeout = sessionTimeout || defaultSessionTimeout;
95
+ revisedSessionTimeout = Math.min(revisedSessionTimeout, maxSessionTimeout);
96
+ revisedSessionTimeout = Math.max(revisedSessionTimeout, minSessionTimeout);
97
+ return revisedSessionTimeout;
98
+ }
99
+ function channel_has_session(channel, session) {
100
+ if (session.channel === channel) {
101
+ (0, node_opcua_assert_1.assert)(Object.prototype.hasOwnProperty.call(channel.sessionTokens, session.authenticationToken.toString()));
102
+ return true;
103
+ }
104
+ return false;
105
+ }
106
+ function moveSessionToChannel(session, channel) {
107
+ debugLog("moveSessionToChannel sessionId", session.nodeId, " channelId=", channel.channelId);
108
+ if (session.publishEngine) {
109
+ session.publishEngine.cancelPendingPublishRequestBeforeChannelChange();
110
+ }
111
+ session._detach_channel();
112
+ session._attach_channel(channel);
113
+ (0, node_opcua_assert_1.assert)(session.channel.channelId === channel.channelId);
114
+ }
115
+ function _attempt_to_close_some_old_unactivated_session(server) {
116
+ return __awaiter(this, void 0, void 0, function* () {
117
+ const session = server.engine.getOldestInactiveSession();
118
+ if (session) {
119
+ yield server.engine.closeSession(session.authenticationToken, false, "Forcing");
120
+ }
121
+ });
122
+ }
123
+ function getRequiredEndpointInfo(endpoint) {
124
+ (0, node_opcua_assert_1.assert)(endpoint instanceof node_opcua_types_1.EndpointDescription);
125
+ // https://reference.opcfoundation.org/v104/Core/docs/Part4/5.6.2/
126
+ // https://reference.opcfoundation.org/v105/Core/docs/Part4/5.6.2/
127
+ const e = new node_opcua_types_1.EndpointDescription({
128
+ endpointUrl: endpoint.endpointUrl,
129
+ securityLevel: endpoint.securityLevel,
130
+ securityMode: endpoint.securityMode,
131
+ securityPolicyUri: endpoint.securityPolicyUri,
132
+ server: {
133
+ applicationUri: endpoint.server.applicationUri,
134
+ applicationType: endpoint.server.applicationType,
135
+ applicationName: endpoint.server.applicationName,
136
+ productUri: endpoint.server.productUri
137
+ },
138
+ transportProfileUri: endpoint.transportProfileUri,
139
+ userIdentityTokens: endpoint.userIdentityTokens
140
+ });
141
+ // reduce even further by explicitly setting unwanted members to null
142
+ e.server.applicationName = null;
143
+ // xx e.server.applicationType = null as any;
144
+ e.server.gatewayServerUri = null;
145
+ e.server.discoveryProfileUri = null;
146
+ e.server.discoveryUrls = null;
147
+ e.serverCertificate = null;
148
+ return e;
149
+ }
150
+ // serverUri String This value is only specified if the EndpointDescription has a gatewayServerUri.
151
+ // This value is the applicationUri from the EndpointDescription which is the applicationUri for the
152
+ // underlying Server. The type EndpointDescription is defined in 7.10.
153
+ function _serverEndpointsForCreateSessionResponse(server, endpointUrl, serverUri) {
154
+ serverUri = null; // unused then
155
+ // https://reference.opcfoundation.org/v104/Core/docs/Part4/5.6.2/
156
+ // https://reference.opcfoundation.org/v105/Core/docs/Part4/5.6.2/
157
+ return server
158
+ ._get_endpoints(endpointUrl)
159
+ .filter((e) => !e.restricted) // remove restricted endpoints
160
+ .filter((e) => (0, node_opcua_utils_1.matchUri)(e.endpointUrl, endpointUrl))
161
+ .map(getRequiredEndpointInfo);
162
+ }
163
+ function adjustSecurityPolicy(channel, userTokenPolicy_securityPolicyUri) {
164
+ // check that userIdentityToken
165
+ let securityPolicy = (0, node_opcua_secure_channel_1.fromURI)(userTokenPolicy_securityPolicyUri);
166
+ // if the security policy is not specified we use the session security policy
167
+ if (securityPolicy === node_opcua_secure_channel_1.SecurityPolicy.Invalid) {
168
+ securityPolicy = (0, node_opcua_secure_channel_1.fromURI)(channel.clientSecurityHeader.securityPolicyUri);
169
+ (0, node_opcua_assert_1.assert)(securityPolicy !== node_opcua_secure_channel_1.SecurityPolicy.Invalid);
170
+ }
171
+ return securityPolicy;
172
+ }
173
+ function findUserTokenByPolicy(endpoint_description, userTokenType, policyId) {
174
+ (0, node_opcua_assert_1.assert)(endpoint_description instanceof node_opcua_types_1.EndpointDescription);
175
+ const r = endpoint_description.userIdentityTokens.filter((userIdentity) => userIdentity.tokenType === userTokenType && (!policyId || userIdentity.policyId === policyId));
176
+ return r.length === 0 ? null : r[0];
177
+ }
178
+ function findUserTokenPolicy(endpoint_description, userTokenType) {
179
+ (0, node_opcua_assert_1.assert)(endpoint_description instanceof node_opcua_types_1.EndpointDescription);
180
+ const r = endpoint_description.userIdentityTokens.filter((userIdentity) => {
181
+ (0, node_opcua_assert_1.assert)(userIdentity.tokenType !== undefined);
182
+ return userIdentity.tokenType === userTokenType;
183
+ });
184
+ return r.length === 0 ? null : r[0];
185
+ }
186
+ function createAnonymousIdentityToken(endpoint_desc) {
187
+ (0, node_opcua_assert_1.assert)(endpoint_desc instanceof node_opcua_types_1.EndpointDescription);
188
+ const userTokenPolicy = findUserTokenPolicy(endpoint_desc, node_opcua_service_endpoints_1.UserTokenType.Anonymous);
189
+ if (!userTokenPolicy) {
190
+ throw new Error("Cannot find ANONYMOUS user token policy in end point description");
191
+ }
192
+ return new node_opcua_service_session_1.AnonymousIdentityToken({ policyId: userTokenPolicy.policyId });
193
+ }
194
+ function sameIdentityToken(token1, token2) {
195
+ if (token1 instanceof node_opcua_service_session_1.UserNameIdentityToken) {
196
+ if (!(token2 instanceof node_opcua_service_session_1.UserNameIdentityToken)) {
197
+ return false;
198
+ }
199
+ if (token1.userName !== token2.userName) {
200
+ return false;
201
+ }
202
+ if (token1.password.toString("hex") !== token2.password.toString("hex")) {
203
+ return false;
204
+ }
205
+ }
206
+ else if (token1 instanceof node_opcua_service_session_1.AnonymousIdentityToken) {
207
+ if (!(token2 instanceof node_opcua_service_session_1.AnonymousIdentityToken)) {
208
+ return false;
209
+ }
210
+ if (token1.policyId !== token2.policyId) {
211
+ return false;
212
+ }
213
+ return true;
214
+ }
215
+ (0, node_opcua_assert_1.assert)(false, " Not implemented yet");
216
+ return false;
217
+ }
218
+ function getTokenType(userIdentityToken) {
219
+ if (userIdentityToken instanceof node_opcua_service_session_1.AnonymousIdentityToken) {
220
+ return node_opcua_service_endpoints_1.UserTokenType.Anonymous;
221
+ }
222
+ else if (userIdentityToken instanceof node_opcua_service_session_1.UserNameIdentityToken) {
223
+ return node_opcua_service_endpoints_1.UserTokenType.UserName;
224
+ }
225
+ else if (userIdentityToken instanceof node_opcua_types_1.IssuedIdentityToken) {
226
+ return node_opcua_service_endpoints_1.UserTokenType.IssuedToken;
227
+ }
228
+ else if (userIdentityToken instanceof node_opcua_service_session_1.X509IdentityToken) {
229
+ return node_opcua_service_endpoints_1.UserTokenType.Certificate;
230
+ }
231
+ return node_opcua_service_endpoints_1.UserTokenType.Invalid;
232
+ }
233
+ function thumbprint(certificate) {
234
+ return certificate ? certificate.toString("base64") : "";
235
+ }
236
+ /*=== private
237
+ *
238
+ * perform the read operation on a given node for a monitored item.
239
+ * this method DOES NOT apply to Variable Values attribute
240
+ *
241
+ * @param self
242
+ * @param oldValue
243
+ * @param node
244
+ * @param itemToMonitor
245
+ * @private
246
+ */
247
+ function monitoredItem_read_and_record_value(self, context, oldValue, node, itemToMonitor, callback) {
248
+ (0, node_opcua_assert_1.assert)(self instanceof monitored_item_1.MonitoredItem);
249
+ (0, node_opcua_assert_1.assert)(oldValue instanceof node_opcua_data_value_1.DataValue);
250
+ (0, node_opcua_assert_1.assert)(itemToMonitor.attributeId === node_opcua_data_model_1.AttributeIds.Value);
251
+ const dataValue = node.readAttribute(context, itemToMonitor.attributeId, itemToMonitor.indexRange, itemToMonitor.dataEncoding);
252
+ callback(null, dataValue);
253
+ }
254
+ /*== private
255
+ * @method monitoredItem_read_and_record_value_async
256
+ * this method applies to Variable Values attribute
257
+ * @param self
258
+ * @param oldValue
259
+ * @param node
260
+ * @param itemToMonitor
261
+ * @private
262
+ */
263
+ function monitoredItem_read_and_record_value_async(self, context, oldValue, node, itemToMonitor, callback) {
264
+ (0, node_opcua_assert_1.assert)(context instanceof node_opcua_address_space_1.SessionContext);
265
+ (0, node_opcua_assert_1.assert)(itemToMonitor.attributeId === node_opcua_data_model_1.AttributeIds.Value);
266
+ (0, node_opcua_assert_1.assert)(self instanceof monitored_item_1.MonitoredItem);
267
+ (0, node_opcua_assert_1.assert)(oldValue instanceof node_opcua_data_value_1.DataValue);
268
+ // do it asynchronously ( this is only valid for value attributes )
269
+ (0, node_opcua_assert_1.assert)(itemToMonitor.attributeId === node_opcua_data_model_1.AttributeIds.Value);
270
+ node.readValueAsync(context, (err, dataValue) => {
271
+ callback(err, dataValue);
272
+ });
273
+ }
274
+ function build_scanning_node_function(context, addressSpace, monitoredItem, itemToMonitor) {
275
+ (0, node_opcua_assert_1.assert)(context instanceof node_opcua_address_space_1.SessionContext);
276
+ (0, node_opcua_assert_1.assert)(itemToMonitor instanceof node_opcua_service_read_1.ReadValueId);
277
+ const node = addressSpace.findNode(itemToMonitor.nodeId);
278
+ /* istanbul ignore next */
279
+ if (!node) {
280
+ errorLog(" INVALID NODE ID , ", itemToMonitor.nodeId.toString());
281
+ (0, node_opcua_debug_1.dump)(itemToMonitor);
282
+ return (oldData, callback) => {
283
+ callback(null, new node_opcua_data_value_1.DataValue({
284
+ statusCode: node_opcua_status_code_1.StatusCodes.BadNodeIdUnknown,
285
+ value: { dataType: node_opcua_variant_1.DataType.Null, value: 0 }
286
+ }));
287
+ };
288
+ }
289
+ ///// !!monitoredItem.setNode(node);
290
+ if (itemToMonitor.attributeId === node_opcua_data_model_1.AttributeIds.Value) {
291
+ const monitoredItem_read_and_record_value_func = itemToMonitor.attributeId === node_opcua_data_model_1.AttributeIds.Value && typeof node.readValueAsync === "function"
292
+ ? monitoredItem_read_and_record_value_async
293
+ : monitoredItem_read_and_record_value;
294
+ return function func(oldDataValue, callback) {
295
+ (0, node_opcua_assert_1.assert)(this instanceof monitored_item_1.MonitoredItem);
296
+ (0, node_opcua_assert_1.assert)(oldDataValue instanceof node_opcua_data_value_1.DataValue);
297
+ (0, node_opcua_assert_1.assert)(typeof callback === "function");
298
+ monitoredItem_read_and_record_value_func(this, context, oldDataValue, node, itemToMonitor, callback);
299
+ };
300
+ }
301
+ else {
302
+ // Attributes, other than the Value Attribute, are only monitored for a change in value.
303
+ // The filter is not used for these Attributes. Any change in value for these Attributes
304
+ // causes a Notification to be generated.
305
+ // only record value when it has changed
306
+ return function func(oldDataValue, callback) {
307
+ (0, node_opcua_assert_1.assert)(this instanceof monitored_item_1.MonitoredItem);
308
+ (0, node_opcua_assert_1.assert)(oldDataValue instanceof node_opcua_data_value_1.DataValue);
309
+ (0, node_opcua_assert_1.assert)(typeof callback === "function");
310
+ const newDataValue = node.readAttribute(null, itemToMonitor.attributeId);
311
+ callback(null, newDataValue);
312
+ };
313
+ }
314
+ }
315
+ function prepareMonitoredItem(context, addressSpace, monitoredItem) {
316
+ const itemToMonitor = monitoredItem.itemToMonitor;
317
+ const readNodeFunc = build_scanning_node_function(context, addressSpace, monitoredItem, itemToMonitor);
318
+ monitoredItem.samplingFunc = readNodeFunc;
319
+ }
320
+ function isMonitoringModeValid(monitoringMode) {
321
+ (0, node_opcua_assert_1.assert)(node_opcua_types_1.MonitoringMode.Invalid !== undefined);
322
+ return monitoringMode !== node_opcua_types_1.MonitoringMode.Invalid && monitoringMode <= node_opcua_types_1.MonitoringMode.Reporting;
323
+ }
324
+ function _installRegisterServerManager(self) {
325
+ (0, node_opcua_assert_1.assert)(self instanceof OPCUAServer);
326
+ (0, node_opcua_assert_1.assert)(!self.registerServerManager);
327
+ /* istanbul ignore next */
328
+ if (!self.registerServerMethod) {
329
+ throw new Error("Internal Error");
330
+ }
331
+ switch (self.registerServerMethod) {
332
+ case RegisterServerMethod.HIDDEN:
333
+ self.registerServerManager = new register_server_manager_hidden_1.RegisterServerManagerHidden({
334
+ server: self
335
+ });
336
+ break;
337
+ case RegisterServerMethod.MDNS:
338
+ self.registerServerManager = new register_server_manager_mdns_only_1.RegisterServerManagerMDNSONLY({
339
+ server: self
340
+ });
341
+ break;
342
+ case RegisterServerMethod.LDS:
343
+ self.registerServerManager = new register_server_manager_1.RegisterServerManager({
344
+ discoveryServerEndpointUrl: self.discoveryServerEndpointUrl,
345
+ server: self
346
+ });
347
+ break;
348
+ /* istanbul ignore next */
349
+ default:
350
+ throw new Error("Invalid switch");
351
+ }
352
+ self.registerServerManager.on("serverRegistrationPending", () => {
353
+ /**
354
+ * emitted when the server is trying to registered the LDS
355
+ * but when the connection to the lds has failed
356
+ * serverRegistrationPending is sent when the backoff signal of the
357
+ * connection process is raised
358
+ * @event serverRegistrationPending
359
+ */
360
+ debugLog("serverRegistrationPending");
361
+ self.emit("serverRegistrationPending");
362
+ });
363
+ self.registerServerManager.on("serverRegistered", () => {
364
+ /**
365
+ * emitted when the server is successfully registered to the LDS
366
+ * @event serverRegistered
367
+ */
368
+ debugLog("serverRegistered");
369
+ self.emit("serverRegistered");
370
+ });
371
+ self.registerServerManager.on("serverRegistrationRenewed", () => {
372
+ /**
373
+ * emitted when the server has successfully renewed its registration to the LDS
374
+ * @event serverRegistrationRenewed
375
+ */
376
+ debugLog("serverRegistrationRenewed");
377
+ self.emit("serverRegistrationRenewed");
378
+ });
379
+ self.registerServerManager.on("serverUnregistered", () => {
380
+ debugLog("serverUnregistered");
381
+ /**
382
+ * emitted when the server is successfully unregistered to the LDS
383
+ * ( for instance during shutdown)
384
+ * @event serverUnregistered
385
+ */
386
+ self.emit("serverUnregistered");
387
+ });
388
+ }
389
+ function validate_applicationUri(channel, request) {
390
+ var _a, _b;
391
+ const applicationUri = request.clientDescription.applicationUri;
392
+ const clientCertificate = request.clientCertificate;
393
+ // if session is insecure there is no need to check certificate information
394
+ if (channel.securityMode === node_opcua_secure_channel_1.MessageSecurityMode.None) {
395
+ return true; // assume correct
396
+ }
397
+ if (!clientCertificate || clientCertificate.length === 0) {
398
+ return true; // can't check
399
+ }
400
+ const e = (0, node_opcua_crypto_1.exploreCertificate)(clientCertificate);
401
+ const uniformResourceIdentifier = (_b = (_a = e.tbsCertificate.extensions.subjectAltName) === null || _a === void 0 ? void 0 : _a.uniformResourceIdentifier) !== null && _b !== void 0 ? _b : null;
402
+ const applicationUriFromCert = uniformResourceIdentifier && uniformResourceIdentifier.length > 0 ? uniformResourceIdentifier[0] : null;
403
+ /* istanbul ignore next */
404
+ if (applicationUriFromCert !== applicationUri) {
405
+ errorLog("BadCertificateUriInvalid!");
406
+ errorLog("applicationUri = ", applicationUri);
407
+ errorLog("applicationUriFromCert = ", applicationUriFromCert);
408
+ }
409
+ return applicationUriFromCert === applicationUri;
410
+ }
411
+ function validate_security_endpoint(server, request, channel) {
412
+ debugLog("validate_security_endpoint = ", request.endpointUrl);
413
+ let endpoints = server._get_endpoints(request.endpointUrl);
414
+ // endpointUrl String The network address that the Client used to access the Session Endpoint.
415
+ // The HostName portion of the URL should be one of the HostNames for the application that are
416
+ // specified in the Server’s ApplicationInstanceCertificate (see 7.2). The Server shall raise an
417
+ // AuditUrlMismatchEventType event if the URL does not match the Server’s HostNames.
418
+ // AuditUrlMismatchEventType event type is defined in Part 5.
419
+ // The Server uses this information for diagnostics and to determine the set of
420
+ // EndpointDescriptions to return in the response.
421
+ // ToDo: check endpointUrl validity and emit an AuditUrlMismatchEventType event if not
422
+ if (endpoints.length === 0) {
423
+ // we have a UrlMismatch here
424
+ const ua_server = server.engine.addressSpace.rootFolder.objects.server;
425
+ ua_server.raiseEvent("AuditUrlMismatchEventType", {
426
+ endpointUrl: { dataType: node_opcua_variant_1.DataType.String, value: request.endpointUrl }
427
+ });
428
+ debugLog("Cannot find endpoint in available endpoints with endpointUri", request.endpointUrl);
429
+ if (OPCUAServer.requestExactEndpointUrl) {
430
+ return { errCode: node_opcua_status_code_1.StatusCodes.BadServiceUnsupported };
431
+ }
432
+ else {
433
+ endpoints = server._get_endpoints(null);
434
+ }
435
+ }
436
+ // ignore restricted endpoints
437
+ endpoints = endpoints.filter((e) => !e.restricted);
438
+ const endpoints_matching_security_mode = endpoints.filter((e) => {
439
+ return e.securityMode === channel.securityMode;
440
+ });
441
+ if (endpoints_matching_security_mode.length === 0) {
442
+ return { errCode: node_opcua_status_code_1.StatusCodes.BadSecurityModeRejected };
443
+ }
444
+ const endpoints_matching_security_policy = endpoints_matching_security_mode.filter((e) => {
445
+ return e.securityPolicyUri === channel.securityHeader.securityPolicyUri;
446
+ });
447
+ if (endpoints_matching_security_policy.length === 0) {
448
+ return { errCode: node_opcua_status_code_1.StatusCodes.BadSecurityPolicyRejected };
449
+ }
450
+ if (endpoints_matching_security_policy.length !== 1) {
451
+ debugLog("endpoints_matching_security_policy= ", endpoints_matching_security_policy.length);
452
+ }
453
+ return { errCode: node_opcua_status_code_1.StatusCodes.Good, endpoint: endpoints_matching_security_policy[0] };
454
+ }
455
+ function filterDiagnosticInfo(returnDiagnostics, response) {
456
+ if (node_opcua_data_model_1.RESPONSE_DIAGNOSTICS_MASK_ALL & returnDiagnostics) {
457
+ response.responseHeader.serviceDiagnostics = (0, node_opcua_data_model_1.filterDiagnosticServiceLevel)(returnDiagnostics, response.responseHeader.serviceDiagnostics);
458
+ if (response.diagnosticInfos && response.diagnosticInfos.length > 0) {
459
+ response.diagnosticInfos = response.diagnosticInfos.map((d) => (0, node_opcua_data_model_1.filterDiagnosticOperationLevel)(returnDiagnostics, d));
460
+ }
461
+ else {
462
+ response.diagnosticInfos = [];
463
+ }
464
+ if (response.results) {
465
+ for (const entry of response.results) {
466
+ if (entry.inputArgumentDiagnosticInfos && entry.inputArgumentDiagnosticInfos.length > 0) {
467
+ entry.inputArgumentDiagnosticInfos = entry.inputArgumentDiagnosticInfos.map((d) => (0, node_opcua_data_model_1.filterDiagnosticOperationLevel)(returnDiagnostics, d));
468
+ }
469
+ else {
470
+ entry.inputArgumentDiagnosticInfos = [];
471
+ }
472
+ }
473
+ }
474
+ }
475
+ }
476
+ exports.filterDiagnosticInfo = filterDiagnosticInfo;
477
+ var RegisterServerMethod;
478
+ (function (RegisterServerMethod) {
479
+ RegisterServerMethod[RegisterServerMethod["HIDDEN"] = 1] = "HIDDEN";
480
+ RegisterServerMethod[RegisterServerMethod["MDNS"] = 2] = "MDNS";
481
+ RegisterServerMethod[RegisterServerMethod["LDS"] = 3] = "LDS"; // the server registers itself to the LDS or LDS-ME (Local Discovery Server)
482
+ })(RegisterServerMethod = exports.RegisterServerMethod || (exports.RegisterServerMethod = {}));
483
+ const g_requestExactEndpointUrl = !!process.env.NODEOPCUA_SERVER_REQUEST_EXACT_ENDPOINT_URL;
484
+ /**
485
+ *
486
+ */
487
+ class OPCUAServer extends base_server_1.OPCUABaseServer {
488
+ constructor(options) {
489
+ super(options);
490
+ /**
491
+ * false if anonymous connection are not allowed
492
+ */
493
+ this.allowAnonymous = false;
494
+ this.allowAnonymous = false;
495
+ options = options || {};
496
+ this.options = options;
497
+ if (options.maxAllowedSessionNumber !== undefined) {
498
+ warningLog("[NODE-OPCUA-W21] maxAllowedSessionNumber property is now deprecated , please use serverCapabilities.maxSessions instead");
499
+ options.serverCapabilities = options.serverCapabilities || {};
500
+ options.serverCapabilities.maxSessions = options.maxAllowedSessionNumber;
501
+ }
502
+ /**
503
+ * @property maxConnectionsPerEndpoint
504
+ */
505
+ this.maxConnectionsPerEndpoint = options.maxConnectionsPerEndpoint || default_maxConnectionsPerEndpoint;
506
+ // build Info
507
+ const buildInfo = Object.assign(Object.assign({}, default_build_info), options.buildInfo);
508
+ // repair product name
509
+ buildInfo.productUri = buildInfo.productUri || this.serverInfo.productUri;
510
+ this.serverInfo.productUri = this.serverInfo.productUri || buildInfo.productUri;
511
+ this.userManager = (0, user_manager_1.makeUserManager)(options.userManager);
512
+ options.allowAnonymous = options.allowAnonymous === undefined ? true : !!options.allowAnonymous;
513
+ /**
514
+ * @property allowAnonymous
515
+ */
516
+ this.allowAnonymous = options.allowAnonymous;
517
+ this.discoveryServerEndpointUrl = options.discoveryServerEndpointUrl || "opc.tcp://%FQDN%:4840";
518
+ (0, node_opcua_assert_1.assert)(typeof this.discoveryServerEndpointUrl === "string");
519
+ this.serverInfo.applicationType = node_opcua_service_endpoints_1.ApplicationType.Server;
520
+ this.capabilitiesForMDNS = options.capabilitiesForMDNS || ["NA"];
521
+ this.registerServerMethod = options.registerServerMethod || RegisterServerMethod.HIDDEN;
522
+ _installRegisterServerManager(this);
523
+ if (!options.userCertificateManager) {
524
+ this.userCertificateManager = (0, node_opcua_certificate_manager_1.getDefaultCertificateManager)("UserPKI");
525
+ }
526
+ else {
527
+ this.userCertificateManager = options.userCertificateManager;
528
+ }
529
+ // note: we need to delay initialization of endpoint as certain resources
530
+ // such as %FQDN% might not be ready yet at this stage
531
+ this._delayInit = () => __awaiter(this, void 0, void 0, function* () {
532
+ /* istanbul ignore next */
533
+ if (!options) {
534
+ throw new Error("Internal Error");
535
+ }
536
+ // to check => this.serverInfo.applicationName = this.serverInfo.productName || buildInfo.productName;
537
+ // note: applicationUri is handled in a special way
538
+ this.engine = new server_engine_1.ServerEngine({
539
+ applicationUri: () => this.serverInfo.applicationUri,
540
+ buildInfo,
541
+ isAuditing: options.isAuditing,
542
+ serverCapabilities: options.serverCapabilities
543
+ });
544
+ this.objectFactory = new factory_1.Factory(this.engine);
545
+ const endpointDefinitions = options.alternateEndpoints || [];
546
+ const hostname = (0, node_opcua_hostname_1.getFullyQualifiedDomainName)();
547
+ endpointDefinitions.push({
548
+ port: options.port || 26543,
549
+ allowAnonymous: options.allowAnonymous,
550
+ alternateHostname: options.alternateHostname,
551
+ disableDiscovery: options.disableDiscovery,
552
+ hostname: options.hostname || hostname,
553
+ securityModes: options.securityModes,
554
+ securityPolicies: options.securityPolicies
555
+ });
556
+ // todo should self.serverInfo.productUri match self.engine.buildInfo.productUri ?
557
+ for (const endpointOptions of endpointDefinitions) {
558
+ const endPoint = this.createEndpointDescriptions(options, endpointOptions);
559
+ this.endpoints.push(endPoint);
560
+ endPoint.on("message", (message, channel) => {
561
+ this.on_request(message, channel);
562
+ });
563
+ endPoint.on("error", (err) => {
564
+ errorLog("OPCUAServer endpoint error", err);
565
+ // set serverState to ServerState.Failed;
566
+ this.engine.setServerState(node_opcua_common_1.ServerState.Failed);
567
+ this.shutdown(() => {
568
+ /* empty */
569
+ });
570
+ });
571
+ }
572
+ });
573
+ }
574
+ /**
575
+ * total number of bytes written by the server since startup
576
+ */
577
+ get bytesWritten() {
578
+ return this.endpoints.reduce((accumulated, endpoint) => {
579
+ return accumulated + endpoint.bytesWritten;
580
+ }, 0);
581
+ }
582
+ /**
583
+ * total number of bytes read by the server since startup
584
+ */
585
+ get bytesRead() {
586
+ return this.endpoints.reduce((accumulated, endpoint) => {
587
+ return accumulated + endpoint.bytesRead;
588
+ }, 0);
589
+ }
590
+ /**
591
+ * Number of transactions processed by the server since startup
592
+ */
593
+ get transactionsCount() {
594
+ return this.endpoints.reduce((accumulated, endpoint) => {
595
+ return accumulated + endpoint.transactionsCount;
596
+ }, 0);
597
+ }
598
+ /**
599
+ * The server build info
600
+ */
601
+ get buildInfo() {
602
+ return this.engine.buildInfo;
603
+ }
604
+ /**
605
+ * the number of connected channel on all existing end points
606
+ */
607
+ get currentChannelCount() {
608
+ // TODO : move to base
609
+ return this.endpoints.reduce((currentValue, endPoint) => {
610
+ return currentValue + endPoint.currentChannelCount;
611
+ }, 0);
612
+ }
613
+ /**
614
+ * The number of active subscriptions from all sessions
615
+ */
616
+ get currentSubscriptionCount() {
617
+ return this.engine ? this.engine.currentSubscriptionCount : 0;
618
+ }
619
+ /**
620
+ * the number of session activation requests that have been rejected
621
+ */
622
+ get rejectedSessionCount() {
623
+ return this.engine ? this.engine.rejectedSessionCount : 0;
624
+ }
625
+ /**
626
+ * the number of request that have been rejected
627
+ */
628
+ get rejectedRequestsCount() {
629
+ return this.engine ? this.engine.rejectedRequestsCount : 0;
630
+ }
631
+ /**
632
+ * the number of sessions that have been aborted
633
+ */
634
+ get sessionAbortCount() {
635
+ return this.engine ? this.engine.sessionAbortCount : 0;
636
+ }
637
+ /**
638
+ * the publishing interval count
639
+ */
640
+ get publishingIntervalCount() {
641
+ return this.engine ? this.engine.publishingIntervalCount : 0;
642
+ }
643
+ /**
644
+ * the number of sessions currently active
645
+ */
646
+ get currentSessionCount() {
647
+ return this.engine ? this.engine.currentSessionCount : 0;
648
+ }
649
+ /**
650
+ * true if the server has been initialized
651
+ *
652
+ */
653
+ get initialized() {
654
+ return this.engine && this.engine.addressSpace !== null;
655
+ }
656
+ /**
657
+ * is the server auditing ?
658
+ */
659
+ get isAuditing() {
660
+ return this.engine ? this.engine.isAuditing : false;
661
+ }
662
+ /**
663
+ * the maximum number of concurrent sessions allowed on the server
664
+ */
665
+ get maxAllowedSessionNumber() {
666
+ return this.engine.serverCapabilities.maxSessions;
667
+ }
668
+ initialize(...args) {
669
+ const done = args[0];
670
+ (0, node_opcua_assert_1.assert)(!this.initialized, "server is already initialized"); // already initialized ?
671
+ this._preInitTask.push(() => __awaiter(this, void 0, void 0, function* () {
672
+ /* istanbul ignore else */
673
+ if (this._delayInit) {
674
+ yield this._delayInit();
675
+ this._delayInit = undefined;
676
+ }
677
+ }));
678
+ this.performPreInitialization()
679
+ .then(() => {
680
+ OPCUAServer.registry.register(this);
681
+ this.engine.initialize(this.options, () => {
682
+ (0, user_manager_ua_1.bindRoleSet)(this.userManager, this.engine.addressSpace);
683
+ setImmediate(() => {
684
+ this.emit("post_initialize");
685
+ done();
686
+ });
687
+ });
688
+ })
689
+ .catch((err) => {
690
+ done(err);
691
+ });
692
+ }
693
+ start(...args) {
694
+ const done = args[0];
695
+ const tasks = [];
696
+ tasks.push((0, util_1.callbackify)(node_opcua_hostname_1.extractFullyQualifiedDomainName));
697
+ if (!this.initialized) {
698
+ tasks.push((callback) => {
699
+ this.initialize(callback);
700
+ });
701
+ }
702
+ tasks.push((callback) => {
703
+ super.start((err) => {
704
+ if (err) {
705
+ this.shutdown((/*err2*/ err2) => {
706
+ callback(err);
707
+ });
708
+ }
709
+ else {
710
+ // we start the registration process asynchronously
711
+ // as we want to make server immediately available
712
+ this.registerServerManager.start(() => {
713
+ /* empty */
714
+ });
715
+ setImmediate(callback);
716
+ }
717
+ });
718
+ });
719
+ async.series(tasks, done);
720
+ }
721
+ shutdown(...args) {
722
+ const timeout = args.length === 1 ? OPCUAServer.defaultShutdownTimeout : args[0];
723
+ const callback = (args.length === 1 ? args[0] : args[1]);
724
+ (0, node_opcua_assert_1.assert)(typeof callback === "function");
725
+ debugLog("OPCUAServer#shutdown (timeout = ", timeout, ")");
726
+ /* istanbul ignore next */
727
+ if (!this.engine) {
728
+ return callback();
729
+ }
730
+ (0, node_opcua_assert_1.assert)(this.engine);
731
+ if (!this.engine.isStarted()) {
732
+ // server may have been shot down already , or may have fail to start !!
733
+ const err = new Error("OPCUAServer#shutdown failure ! server doesn't seems to be started yet");
734
+ return callback(err);
735
+ }
736
+ this.userCertificateManager.dispose();
737
+ this.engine.setServerState(node_opcua_common_1.ServerState.Shutdown);
738
+ const shutdownTime = new Date(Date.now() + timeout);
739
+ this.engine.setShutdownTime(shutdownTime);
740
+ debugLog("OPCUAServer is now unregistering itself from the discovery server " + this.buildInfo);
741
+ this.registerServerManager.stop((err) => {
742
+ debugLog("OPCUAServer unregistered from discovery server", err);
743
+ setTimeout(() => __awaiter(this, void 0, void 0, function* () {
744
+ yield this.engine.shutdown();
745
+ debugLog("OPCUAServer#shutdown: started");
746
+ base_server_1.OPCUABaseServer.prototype.shutdown.call(this, (err1) => {
747
+ debugLog("OPCUAServer#shutdown: completed");
748
+ this.dispose();
749
+ callback(err1);
750
+ });
751
+ }), timeout);
752
+ });
753
+ }
754
+ dispose() {
755
+ for (const endpoint of this.endpoints) {
756
+ endpoint.dispose();
757
+ }
758
+ this.endpoints = [];
759
+ this.removeAllListeners();
760
+ if (this.registerServerManager) {
761
+ this.registerServerManager.dispose();
762
+ this.registerServerManager = undefined;
763
+ }
764
+ OPCUAServer.registry.unregister(this);
765
+ /* istanbul ignore next */
766
+ if (this.engine) {
767
+ this.engine.dispose();
768
+ }
769
+ }
770
+ raiseEvent(eventType, options) {
771
+ /* istanbul ignore next */
772
+ if (!this.engine.addressSpace) {
773
+ errorLog("addressSpace missing");
774
+ return;
775
+ }
776
+ const server = this.engine.addressSpace.findNode("Server");
777
+ /* istanbul ignore next */
778
+ if (!server) {
779
+ // xx throw new Error("OPCUAServer#raiseEvent : cannot find Server object");
780
+ return;
781
+ }
782
+ let eventTypeNode = eventType;
783
+ if (typeof eventType === "string") {
784
+ eventTypeNode = this.engine.addressSpace.findEventType(eventType);
785
+ if (eventTypeNode) {
786
+ return server.raiseEvent(eventTypeNode, options);
787
+ }
788
+ else {
789
+ console.warn(" cannot find event type ", eventType);
790
+ }
791
+ }
792
+ else {
793
+ return server.raiseEvent(eventTypeNode, options);
794
+ }
795
+ }
796
+ /**
797
+ * create and register a new session
798
+ * @internal
799
+ */
800
+ createSession(options) {
801
+ /* istanbul ignore next */
802
+ if (!this.engine) {
803
+ throw new Error("Internal Error");
804
+ }
805
+ return this.engine.createSession(options);
806
+ }
807
+ /**
808
+ * retrieve a session by authentication token
809
+ * @internal
810
+ */
811
+ getSession(authenticationToken, activeOnly) {
812
+ return this.engine ? this.engine.getSession(authenticationToken, activeOnly) : null;
813
+ }
814
+ /**
815
+ *
816
+ * @param channel
817
+ * @param clientCertificate
818
+ * @param clientNonce
819
+ * @internal
820
+ */
821
+ computeServerSignature(channel, clientCertificate, clientNonce) {
822
+ return (0, node_opcua_secure_channel_1.computeSignature)(clientCertificate, clientNonce, this.getPrivateKey(), channel.messageBuilder.securityPolicy);
823
+ }
824
+ /**
825
+ *
826
+ * @param session
827
+ * @param channel
828
+ * @param clientSignature
829
+ * @internal
830
+ */
831
+ verifyClientSignature(session, channel, clientSignature) {
832
+ const clientCertificate = channel.receiverCertificate;
833
+ const securityPolicy = channel.messageBuilder.securityPolicy;
834
+ const serverCertificate = this.getCertificate();
835
+ const result = (0, node_opcua_secure_channel_1.verifySignature)(serverCertificate, session.nonce, clientSignature, clientCertificate, securityPolicy);
836
+ return result;
837
+ }
838
+ isValidUserNameIdentityToken(channel, session, userTokenPolicy, userIdentityToken, userTokenSignature, callback) {
839
+ (0, node_opcua_assert_1.assert)(userIdentityToken instanceof node_opcua_service_session_1.UserNameIdentityToken);
840
+ const securityPolicy = adjustSecurityPolicy(channel, userTokenPolicy.securityPolicyUri);
841
+ if (securityPolicy === node_opcua_secure_channel_1.SecurityPolicy.None) {
842
+ return callback(null, node_opcua_status_code_1.StatusCodes.Good);
843
+ }
844
+ const cryptoFactory = (0, node_opcua_secure_channel_1.getCryptoFactory)(securityPolicy);
845
+ /* istanbul ignore next */
846
+ if (!cryptoFactory) {
847
+ return callback(null, node_opcua_status_code_1.StatusCodes.BadSecurityPolicyRejected);
848
+ }
849
+ /* istanbul ignore next */
850
+ if (userIdentityToken.encryptionAlgorithm !== cryptoFactory.asymmetricEncryptionAlgorithm) {
851
+ errorLog("invalid encryptionAlgorithm");
852
+ errorLog("userTokenPolicy", userTokenPolicy.toString());
853
+ errorLog("userTokenPolicy", userIdentityToken.toString());
854
+ return callback(null, node_opcua_status_code_1.StatusCodes.BadIdentityTokenInvalid);
855
+ }
856
+ const userName = userIdentityToken.userName;
857
+ const password = userIdentityToken.password;
858
+ if (!userName || !password) {
859
+ return callback(null, node_opcua_status_code_1.StatusCodes.BadIdentityTokenInvalid);
860
+ }
861
+ return callback(null, node_opcua_status_code_1.StatusCodes.Good);
862
+ }
863
+ isValidX509IdentityToken(channel, session, userTokenPolicy, userIdentityToken, userTokenSignature, callback) {
864
+ (0, node_opcua_assert_1.assert)(userIdentityToken instanceof node_opcua_service_session_1.X509IdentityToken);
865
+ (0, node_opcua_assert_1.assert)(typeof callback === "function");
866
+ const securityPolicy = adjustSecurityPolicy(channel, userTokenPolicy.securityPolicyUri);
867
+ const cryptoFactory = (0, node_opcua_secure_channel_1.getCryptoFactory)(securityPolicy);
868
+ /* istanbul ignore next */
869
+ if (!cryptoFactory) {
870
+ return callback(null, node_opcua_status_code_1.StatusCodes.BadSecurityPolicyRejected);
871
+ }
872
+ if (!userTokenSignature || !userTokenSignature.signature) {
873
+ this.raiseEvent("AuditCreateSessionEventType", {});
874
+ return callback(null, node_opcua_status_code_1.StatusCodes.BadUserSignatureInvalid);
875
+ }
876
+ if (userIdentityToken.policyId !== userTokenPolicy.policyId) {
877
+ errorLog("invalid encryptionAlgorithm");
878
+ errorLog("userTokenPolicy", userTokenPolicy.toString());
879
+ errorLog("userTokenPolicy", userIdentityToken.toString());
880
+ return callback(null, node_opcua_status_code_1.StatusCodes.BadSecurityPolicyRejected);
881
+ }
882
+ const certificate = userIdentityToken.certificateData; /* as Certificate*/
883
+ const nonce = session.nonce;
884
+ const serverCertificate = this.getCertificate();
885
+ (0, node_opcua_assert_1.assert)(serverCertificate instanceof Buffer);
886
+ (0, node_opcua_assert_1.assert)(certificate instanceof Buffer, "expecting certificate to be a Buffer");
887
+ (0, node_opcua_assert_1.assert)(nonce instanceof Buffer, "expecting nonce to be a Buffer");
888
+ (0, node_opcua_assert_1.assert)(userTokenSignature.signature instanceof Buffer, "expecting userTokenSignature to be a Buffer");
889
+ // verify proof of possession by checking certificate signature & server nonce correctness
890
+ if (!(0, node_opcua_secure_channel_1.verifySignature)(serverCertificate, nonce, userTokenSignature, certificate, securityPolicy)) {
891
+ return callback(null, node_opcua_status_code_1.StatusCodes.BadUserSignatureInvalid);
892
+ }
893
+ // verify if certificate is Valid
894
+ this.userCertificateManager.checkCertificate(certificate, (err, certificateStatus) => {
895
+ /* istanbul ignore next */
896
+ if (err) {
897
+ return callback(err);
898
+ }
899
+ if (this.isAuditing) {
900
+ switch (certificateStatus) {
901
+ case node_opcua_status_code_1.StatusCodes.Good:
902
+ break;
903
+ case node_opcua_status_code_1.StatusCodes.BadCertificateUntrusted:
904
+ this.raiseEvent("AuditCertificateUntrustedEventType", {
905
+ certificate: { dataType: node_opcua_variant_1.DataType.ByteString, value: certificate },
906
+ sourceName: { dataType: node_opcua_variant_1.DataType.String, value: "Security/Certificate" }
907
+ });
908
+ break;
909
+ case node_opcua_status_code_1.StatusCodes.BadCertificateTimeInvalid:
910
+ case node_opcua_status_code_1.StatusCodes.BadCertificateIssuerTimeInvalid:
911
+ this.raiseEvent("AuditCertificateExpiredEventType", {
912
+ certificate: { dataType: node_opcua_variant_1.DataType.ByteString, value: certificate },
913
+ sourceName: { dataType: node_opcua_variant_1.DataType.String, value: "Security/Certificate" },
914
+ comment: { dataType: node_opcua_variant_1.DataType.String, value: certificateStatus.toString() }
915
+ });
916
+ break;
917
+ case node_opcua_status_code_1.StatusCodes.BadCertificateRevoked:
918
+ case node_opcua_status_code_1.StatusCodes.BadCertificateRevocationUnknown:
919
+ case node_opcua_status_code_1.StatusCodes.BadCertificateIssuerRevocationUnknown:
920
+ this.raiseEvent("AuditCertificateRevokedEventType", {
921
+ certificate: { dataType: node_opcua_variant_1.DataType.ByteString, value: certificate },
922
+ sourceName: { dataType: node_opcua_variant_1.DataType.String, value: "Security/Certificate" },
923
+ comment: { dataType: node_opcua_variant_1.DataType.String, value: certificateStatus.toString() }
924
+ });
925
+ break;
926
+ case node_opcua_status_code_1.StatusCodes.BadCertificateIssuerUseNotAllowed:
927
+ case node_opcua_status_code_1.StatusCodes.BadCertificateUseNotAllowed:
928
+ case node_opcua_status_code_1.StatusCodes.BadSecurityChecksFailed:
929
+ this.raiseEvent("AuditCertificateMismatchEventType", {
930
+ certificate: { dataType: node_opcua_variant_1.DataType.ByteString, value: certificate },
931
+ sourceName: { dataType: node_opcua_variant_1.DataType.String, value: "Security/Certificate" },
932
+ comment: { dataType: node_opcua_variant_1.DataType.String, value: certificateStatus.toString() }
933
+ });
934
+ break;
935
+ }
936
+ }
937
+ if (node_opcua_status_code_1.StatusCodes.BadCertificateUntrusted === certificateStatus ||
938
+ node_opcua_status_code_1.StatusCodes.BadCertificateTimeInvalid === certificateStatus ||
939
+ node_opcua_status_code_1.StatusCodes.BadCertificateIssuerTimeInvalid === certificateStatus ||
940
+ node_opcua_status_code_1.StatusCodes.BadCertificateIssuerUseNotAllowed === certificateStatus ||
941
+ node_opcua_status_code_1.StatusCodes.BadCertificateIssuerRevocationUnknown === certificateStatus ||
942
+ node_opcua_status_code_1.StatusCodes.BadCertificateRevocationUnknown === certificateStatus ||
943
+ node_opcua_status_code_1.StatusCodes.BadCertificateRevoked === certificateStatus ||
944
+ node_opcua_status_code_1.StatusCodes.BadCertificateUseNotAllowed === certificateStatus ||
945
+ node_opcua_status_code_1.StatusCodes.BadSecurityChecksFailed === certificateStatus ||
946
+ node_opcua_status_code_1.StatusCodes.Good !== certificateStatus) {
947
+ debugLog("isValidX509IdentityToken => certificateStatus = ", certificateStatus === null || certificateStatus === void 0 ? void 0 : certificateStatus.toString());
948
+ return callback(null, node_opcua_status_code_1.StatusCodes.BadIdentityTokenRejected);
949
+ }
950
+ if (node_opcua_status_code_1.StatusCodes.Good !== certificateStatus) {
951
+ (0, node_opcua_assert_1.assert)(certificateStatus instanceof node_opcua_status_code_1.StatusCode);
952
+ return callback(null, certificateStatus);
953
+ // return callback(null, StatusCodes.BadIdentityTokenInvalid);
954
+ }
955
+ // verify if certificate is truster or rejected
956
+ // todo: StatusCodes.BadCertificateUntrusted
957
+ // store untrusted certificate to rejected folder
958
+ // todo:
959
+ return callback(null, node_opcua_status_code_1.StatusCodes.Good);
960
+ });
961
+ }
962
+ /**
963
+ * @internal
964
+ */
965
+ userNameIdentityTokenAuthenticateUser(channel, session, userTokenPolicy, userIdentityToken, callback) {
966
+ (0, node_opcua_assert_1.assert)(userIdentityToken instanceof node_opcua_service_session_1.UserNameIdentityToken);
967
+ // assert(this.isValidUserNameIdentityToken(channel, session, userTokenPolicy, userIdentityToken));
968
+ const securityPolicy = adjustSecurityPolicy(channel, userTokenPolicy.securityPolicyUri);
969
+ const userName = userIdentityToken.userName;
970
+ let password = userIdentityToken.password;
971
+ // decrypt password if necessary
972
+ if (securityPolicy === node_opcua_secure_channel_1.SecurityPolicy.None) {
973
+ // not good, password was sent in clear text ...
974
+ password = password.toString();
975
+ }
976
+ else {
977
+ const serverPrivateKey = this.getPrivateKey();
978
+ const serverNonce = session.nonce;
979
+ (0, node_opcua_assert_1.assert)(serverNonce instanceof Buffer);
980
+ const cryptoFactory = (0, node_opcua_secure_channel_1.getCryptoFactory)(securityPolicy);
981
+ /* istanbul ignore next */
982
+ if (!cryptoFactory) {
983
+ return callback(new Error(" Unsupported security Policy"));
984
+ }
985
+ const buff = cryptoFactory.asymmetricDecrypt(password, serverPrivateKey);
986
+ // server certificate may be invalid and asymmetricDecrypt may fail
987
+ if (!buff || buff.length < 4) {
988
+ async.setImmediate(() => callback(null, false));
989
+ return;
990
+ }
991
+ const length = buff.readUInt32LE(0) - serverNonce.length;
992
+ password = buff.slice(4, 4 + length).toString("utf-8");
993
+ }
994
+ this.userManager
995
+ .isValidUser(session, userName, password)
996
+ .then((isValid) => callback(null, isValid))
997
+ .catch((err) => callback(err));
998
+ }
999
+ /**
1000
+ * @internal
1001
+ */
1002
+ isValidUserIdentityToken(channel, session, userIdentityToken, userTokenSignature, endpointDescription, callback) {
1003
+ (0, node_opcua_assert_1.assert)(typeof callback === "function");
1004
+ /* istanbul ignore next */
1005
+ if (!userIdentityToken) {
1006
+ throw new Error("Invalid token");
1007
+ }
1008
+ const userTokenType = getTokenType(userIdentityToken);
1009
+ const userTokenPolicy = findUserTokenByPolicy(endpointDescription, userTokenType, userIdentityToken.policyId);
1010
+ if (!userTokenPolicy) {
1011
+ // cannot find token with this policyId
1012
+ return callback(null, node_opcua_status_code_1.StatusCodes.BadIdentityTokenInvalid);
1013
+ }
1014
+ //
1015
+ if (userIdentityToken instanceof node_opcua_service_session_1.UserNameIdentityToken) {
1016
+ return this.isValidUserNameIdentityToken(channel, session, userTokenPolicy, userIdentityToken, userTokenSignature, callback);
1017
+ }
1018
+ if (userIdentityToken instanceof node_opcua_service_session_1.X509IdentityToken) {
1019
+ return this.isValidX509IdentityToken(channel, session, userTokenPolicy, userIdentityToken, userTokenSignature, callback);
1020
+ }
1021
+ return callback(null, node_opcua_status_code_1.StatusCodes.Good);
1022
+ }
1023
+ /**
1024
+ *
1025
+ * @internal
1026
+ * @param channel
1027
+ * @param session
1028
+ * @param userIdentityToken
1029
+ * @param callback
1030
+ * @returns {*}
1031
+ */
1032
+ isUserAuthorized(channel, session, userIdentityToken, callback) {
1033
+ (0, node_opcua_assert_1.assert)(userIdentityToken);
1034
+ (0, node_opcua_assert_1.assert)(typeof callback === "function");
1035
+ const userTokenType = getTokenType(userIdentityToken);
1036
+ const userTokenPolicy = findUserTokenByPolicy(session.getEndpointDescription(), userTokenType, userIdentityToken.policyId);
1037
+ /** istanbul ignore next */
1038
+ if (!userTokenPolicy) {
1039
+ return callback(null, false);
1040
+ }
1041
+ // find if a userToken exists
1042
+ if (userIdentityToken instanceof node_opcua_service_session_1.UserNameIdentityToken) {
1043
+ return this.userNameIdentityTokenAuthenticateUser(channel, session, userTokenPolicy, userIdentityToken, callback);
1044
+ }
1045
+ async.setImmediate(callback.bind(null, null, true));
1046
+ }
1047
+ makeServerNonce() {
1048
+ return crypto.randomBytes(32);
1049
+ }
1050
+ // session services
1051
+ // eslint-disable-next-line max-statements
1052
+ _on_CreateSessionRequest(message, channel) {
1053
+ return __awaiter(this, void 0, void 0, function* () {
1054
+ const request = message.request;
1055
+ (0, node_opcua_assert_1.assert)(request instanceof node_opcua_service_session_1.CreateSessionRequest);
1056
+ function rejectConnection(server, statusCode) {
1057
+ server.engine.incrementSecurityRejectedSessionCount();
1058
+ const response1 = new node_opcua_service_session_1.CreateSessionResponse({
1059
+ responseHeader: { serviceResult: statusCode }
1060
+ });
1061
+ channel.send_response("MSG", response1, message);
1062
+ // and close !
1063
+ }
1064
+ // From OPCUA V1.03 Part 4 5.6.2 CreateSession
1065
+ // A Server application should limit the number of Sessions. To protect against misbehaving Clients and denial
1066
+ // of service attacks, the Server shall close the oldest Session that is not activated before reaching the
1067
+ // maximum number of supported Sessions
1068
+ if (this.currentSessionCount >= this.engine.serverCapabilities.maxSessions) {
1069
+ yield _attempt_to_close_some_old_unactivated_session(this);
1070
+ }
1071
+ // check if session count hasn't reach the maximum allowed sessions
1072
+ if (this.currentSessionCount >= this.engine.serverCapabilities.maxSessions) {
1073
+ return rejectConnection(this, node_opcua_status_code_1.StatusCodes.BadTooManySessions);
1074
+ }
1075
+ // Release 1.03 OPC Unified Architecture, Part 4 page 24 - CreateSession Parameters
1076
+ // client should prove a sessionName
1077
+ // Session name is a Human readable string that identifies the Session. The Server makes this name and the
1078
+ // sessionId visible in its AddressSpace for diagnostic purposes. The Client should provide a name that is
1079
+ // unique for the instance of the Client.
1080
+ // If this parameter is not specified the Server shall assign a value.
1081
+ if (utils.isNullOrUndefined(request.sessionName)) {
1082
+ // see also #198
1083
+ // let's the server assign a sessionName for this lazy client.
1084
+ debugLog("assigning OPCUAServer.fallbackSessionName because client's sessionName is null ", OPCUAServer.fallbackSessionName);
1085
+ request.sessionName = OPCUAServer.fallbackSessionName;
1086
+ }
1087
+ // Duration Requested maximum number of milliseconds that a Session should remain open without activity.
1088
+ // If the Client fails to issue a Service request within this interval, then the Server shall automatically
1089
+ // terminate the Client Session.
1090
+ const revisedSessionTimeout = _adjust_session_timeout(request.requestedSessionTimeout);
1091
+ // Release 1.02 page 27 OPC Unified Architecture, Part 4: CreateSession.clientNonce
1092
+ // A random number that should never be used in any other request. This number shall have a minimum length of 32
1093
+ // bytes. Profiles may increase the required length. The Server shall use this value to prove possession of
1094
+ // its application instance Certificate in the response.
1095
+ if (!request.clientNonce || request.clientNonce.length < 32) {
1096
+ if (channel.securityMode !== node_opcua_secure_channel_1.MessageSecurityMode.None) {
1097
+ errorLog(chalk.red("SERVER with secure connection: Missing or invalid client Nonce "), request.clientNonce && request.clientNonce.toString("hex"));
1098
+ return rejectConnection(this, node_opcua_status_code_1.StatusCodes.BadNonceInvalid);
1099
+ }
1100
+ }
1101
+ if ((0, node_opcua_secure_channel_1.nonceAlreadyBeenUsed)(request.clientNonce)) {
1102
+ errorLog(chalk.red("SERVER with secure connection: None has already been used"), request.clientNonce && request.clientNonce.toString("hex"));
1103
+ return rejectConnection(this, node_opcua_status_code_1.StatusCodes.BadNonceInvalid);
1104
+ }
1105
+ // check application spoofing
1106
+ // check if applicationUri in createSessionRequest matches applicationUri in client Certificate
1107
+ if (!validate_applicationUri(channel, request)) {
1108
+ return rejectConnection(this, node_opcua_status_code_1.StatusCodes.BadCertificateUriInvalid);
1109
+ }
1110
+ const { errCode, endpoint } = validate_security_endpoint(this, request, channel);
1111
+ if (errCode !== node_opcua_status_code_1.StatusCodes.Good) {
1112
+ return rejectConnection(this, errCode);
1113
+ }
1114
+ // see Release 1.02 27 OPC Unified Architecture, Part 4
1115
+ const session = this.createSession({
1116
+ clientDescription: request.clientDescription,
1117
+ sessionTimeout: revisedSessionTimeout
1118
+ });
1119
+ session.endpoint = endpoint;
1120
+ (0, node_opcua_assert_1.assert)(session);
1121
+ (0, node_opcua_assert_1.assert)(session.sessionTimeout === revisedSessionTimeout);
1122
+ session.clientDescription = request.clientDescription;
1123
+ session.sessionName = request.sessionName || `<unknown session name ${unnamed_session_count++}>`;
1124
+ // Depending upon on the SecurityPolicy and the SecurityMode of the SecureChannel, the exchange of
1125
+ // ApplicationInstanceCertificates and Nonces may be optional and the signatures may be empty. See
1126
+ // Part 7 for the definition of SecurityPolicies and the handling of these parameters
1127
+ // serverNonce:
1128
+ // A random number that should never be used in any other request.
1129
+ // This number shall have a minimum length of 32 bytes.
1130
+ // The Client shall use this value to prove possession of its application instance
1131
+ // Certificate in the ActivateSession request.
1132
+ // This value may also be used to prove possession of the userIdentityToken it
1133
+ // specified in the ActivateSession request.
1134
+ //
1135
+ // ( this serverNonce will only be used up to the _on_ActivateSessionRequest
1136
+ // where a new nonce will be created)
1137
+ session.nonce = this.makeServerNonce();
1138
+ session.channelId = channel.channelId;
1139
+ session._attach_channel(channel);
1140
+ const serverCertificateChain = this.getCertificateChain();
1141
+ const hasEncryption = true;
1142
+ // If the securityPolicyUri is None and none of the UserTokenPolicies requires encryption
1143
+ if (session.channel.securityMode === node_opcua_secure_channel_1.MessageSecurityMode.None) {
1144
+ // ToDo: Check that none of our insecure endpoint has a a UserTokenPolicy that require encryption
1145
+ // and set hasEncryption = false under this condition
1146
+ }
1147
+ const response = new node_opcua_service_session_1.CreateSessionResponse({
1148
+ // A identifier which uniquely identifies the session.
1149
+ sessionId: session.nodeId,
1150
+ // A unique identifier assigned by the Server to the Session.
1151
+ // The token used to authenticate the client in subsequent requests.
1152
+ authenticationToken: session.authenticationToken,
1153
+ revisedSessionTimeout,
1154
+ serverNonce: session.nonce,
1155
+ // serverCertificate: type ApplicationServerCertificate
1156
+ // The application instance Certificate issued to the Server.
1157
+ // A Server shall prove possession by using the private key to sign the Nonce provided
1158
+ // by the Client in the request. The Client shall verify that this Certificate is the same as
1159
+ // the one it used to create the SecureChannel.
1160
+ // The ApplicationInstanceCertificate type is defined in OpCUA 1.03 part 4 - $7.2 page 108
1161
+ // If the securityPolicyUri is None and none of the UserTokenPolicies requires
1162
+ // encryption, the Server shall not send an ApplicationInstanceCertificate and the Client
1163
+ // shall ignore the ApplicationInstanceCertificate.
1164
+ serverCertificate: hasEncryption ? serverCertificateChain : undefined,
1165
+ // The endpoints provided by the server.
1166
+ // The Server shall return a set of EndpointDescriptions available for the serverUri
1167
+ // specified in the request.[...]
1168
+ // The Client shall verify this list with the list from a Discovery Endpoint if it used a Discovery
1169
+ // Endpoint to fetch the EndpointDescriptions.
1170
+ // It is recommended that Servers only include the endpointUrl, securityMode,
1171
+ // securityPolicyUri, userIdentityTokens, transportProfileUri and securityLevel with all
1172
+ // other parameters set to null. Only the recommended parameters shall be verified by
1173
+ // the client.
1174
+ serverEndpoints: _serverEndpointsForCreateSessionResponse(this, session.endpoint.endpointUrl, request.serverUri),
1175
+ // This parameter is deprecated and the array shall be empty.
1176
+ serverSoftwareCertificates: null,
1177
+ // This is a signature generated with the private key associated with the
1178
+ // serverCertificate. This parameter is calculated by appending the clientNonce to the
1179
+ // clientCertificate and signing the resulting sequence of bytes.
1180
+ // The SignatureAlgorithm shall be the AsymmetricSignatureAlgorithm specified in the
1181
+ // SecurityPolicy for the Endpoint.
1182
+ // The SignatureData type is defined in 7.30.
1183
+ serverSignature: this.computeServerSignature(channel, request.clientCertificate, request.clientNonce),
1184
+ // The maximum message size accepted by the server
1185
+ // The Client Communication Stack should return a Bad_RequestTooLarge error to the
1186
+ // application if a request message exceeds this limit.
1187
+ // The value zero indicates that this parameter is not used.
1188
+ maxRequestMessageSize: 0x4000000
1189
+ });
1190
+ this.emit("create_session", session);
1191
+ session.on("session_closed", (session1, deleteSubscriptions, reason) => {
1192
+ (0, node_opcua_assert_1.assert)(typeof reason === "string");
1193
+ if (this.isAuditing) {
1194
+ (0, node_opcua_assert_1.assert)(reason === "Timeout" || reason === "Terminated" || reason === "CloseSession" || reason === "Forcing");
1195
+ const sourceName = "Session/" + reason;
1196
+ this.raiseEvent("AuditSessionEventType", {
1197
+ /* part 5 - 6.4.3 AuditEventType */
1198
+ actionTimeStamp: { dataType: "DateTime", value: new Date() },
1199
+ status: { dataType: "Boolean", value: true },
1200
+ serverId: { dataType: "String", value: "" },
1201
+ // ClientAuditEntryId contains the human-readable AuditEntryId defined in Part 3.
1202
+ clientAuditEntryId: { dataType: "String", value: "" },
1203
+ // The ClientUserId identifies the user of the client requesting an action. The ClientUserId can be
1204
+ // obtained from the UserIdentityToken passed in the ActivateSession call.
1205
+ clientUserId: { dataType: "String", value: "" },
1206
+ sourceName: { dataType: "String", value: sourceName },
1207
+ /* part 5 - 6.4.7 AuditSessionEventType */
1208
+ sessionId: { dataType: "NodeId", value: session1.nodeId }
1209
+ });
1210
+ }
1211
+ this.emit("session_closed", session1, deleteSubscriptions);
1212
+ });
1213
+ if (this.isAuditing) {
1214
+ // ------------------------------------------------------------------------------------------------------
1215
+ this.raiseEvent("AuditCreateSessionEventType", {
1216
+ /* part 5 - 6.4.3 AuditEventType */
1217
+ actionTimeStamp: { dataType: "DateTime", value: new Date() },
1218
+ status: { dataType: "Boolean", value: true },
1219
+ serverId: { dataType: "String", value: "" },
1220
+ // ClientAuditEntryId contains the human-readable AuditEntryId defined in Part 3.
1221
+ clientAuditEntryId: { dataType: "String", value: "" },
1222
+ // The ClientUserId identifies the user of the client requesting an action. The ClientUserId can be
1223
+ // obtained from the UserIdentityToken passed in the ActivateSession call.
1224
+ clientUserId: { dataType: "String", value: "" },
1225
+ sourceName: { dataType: "String", value: "Session/CreateSession" },
1226
+ /* part 5 - 6.4.7 AuditSessionEventType */
1227
+ sessionId: { dataType: "NodeId", value: session.nodeId },
1228
+ /* part 5 - 6.4.8 AuditCreateSessionEventType */
1229
+ // SecureChannelId shall uniquely identify the SecureChannel. The application shall use the same
1230
+ // identifier in all AuditEvents related to the Session Service Set (AuditCreateSessionEventType,
1231
+ // AuditActivateSessionEventType and their subtypes) and the SecureChannel Service Set
1232
+ // (AuditChannelEventType and its subtypes
1233
+ secureChannelId: { dataType: "String", value: session.channel.channelId.toString() },
1234
+ // Duration
1235
+ revisedSessionTimeout: { dataType: "Duration", value: session.sessionTimeout },
1236
+ // clientCertificate
1237
+ clientCertificate: { dataType: "ByteString", value: session.channel.clientCertificate },
1238
+ // clientCertificateThumbprint
1239
+ clientCertificateThumbprint: {
1240
+ dataType: "String",
1241
+ value: thumbprint(session.channel.clientCertificate)
1242
+ }
1243
+ });
1244
+ }
1245
+ // -----------------------------------------------------------------------------------------------------------
1246
+ (0, node_opcua_assert_1.assert)(response.authenticationToken);
1247
+ channel.send_response("MSG", response, message);
1248
+ });
1249
+ }
1250
+ // TODO : implement this:
1251
+ //
1252
+ // When the ActivateSession Service is called for the first time then the Server shall reject the request
1253
+ // if the SecureChannel is not same as the one associated with the CreateSession request.
1254
+ // Subsequent calls to ActivateSession may be associated with different SecureChannels. If this is the
1255
+ // case then the Server shall verify that the Certificate the Client used to create the new
1256
+ // SecureChannel is the same as the Certificate used to create the original SecureChannel. In addition,
1257
+ // the Server shall verify that the Client supplied a UserIdentityToken that is identical to the token
1258
+ // currently associated with the Session. Once the Server accepts the new SecureChannel it shall
1259
+ // reject requests sent via the old SecureChannel.
1260
+ /**
1261
+ *
1262
+ * @method _on_ActivateSessionRequest
1263
+ * @private
1264
+ *
1265
+ *
1266
+ */
1267
+ _on_ActivateSessionRequest(message, channel) {
1268
+ const request = message.request;
1269
+ (0, node_opcua_assert_1.assert)(request instanceof node_opcua_service_session_1.ActivateSessionRequest);
1270
+ // get session from authenticationToken
1271
+ const authenticationToken = request.requestHeader.authenticationToken;
1272
+ const session = this.getSession(authenticationToken);
1273
+ function rejectConnection(server, statusCode) {
1274
+ if (statusCode === node_opcua_status_code_1.StatusCodes.BadSessionIdInvalid) {
1275
+ server.engine.incrementRejectedSessionCount();
1276
+ }
1277
+ else {
1278
+ server.engine.incrementRejectedSessionCount();
1279
+ server.engine.incrementSecurityRejectedSessionCount();
1280
+ }
1281
+ const response1 = new node_opcua_service_session_1.ActivateSessionResponse({ responseHeader: { serviceResult: statusCode } });
1282
+ channel.send_response("MSG", response1, message);
1283
+ // and close !
1284
+ }
1285
+ let response;
1286
+ /* istanbul ignore next */
1287
+ if (!session) {
1288
+ // this may happen when the server has been restarted and a client tries to reconnect, thinking
1289
+ // that the previous session may still be active
1290
+ debugLog(chalk.yellow.bold(" Bad Session in _on_ActivateSessionRequest"), authenticationToken.toString());
1291
+ return rejectConnection(this, node_opcua_status_code_1.StatusCodes.BadSessionIdInvalid);
1292
+ }
1293
+ // tslint:disable-next-line: no-unused-expression
1294
+ session.keepAlive ? session.keepAlive() : void 0;
1295
+ // OpcUA 1.02 part 3 $5.6.3.1 ActiveSession Set page 29
1296
+ // When the ActivateSession Service is called f or the first time then the Server shall reject the request
1297
+ // if the SecureChannel is not same as the one associated with the CreateSession request.
1298
+ if (session.status === "new") {
1299
+ // xx if (channel.session_nonce !== session.nonce) {
1300
+ if (!channel_has_session(channel, session)) {
1301
+ // it looks like session activation is being using a channel that is not the
1302
+ // one that have been used to create the session
1303
+ errorLog(" channel.sessionTokens === " + Object.keys(channel.sessionTokens).join(" "));
1304
+ return rejectConnection(this, node_opcua_status_code_1.StatusCodes.BadSessionNotActivated);
1305
+ }
1306
+ }
1307
+ // OpcUA 1.02 part 3 $5.6.3.1 ActiveSession Set page 29
1308
+ // ... Subsequent calls to ActivateSession may be associated with different SecureChannels. If this is the
1309
+ // case then the Server shall verify that the Certificate the Client used to create the new
1310
+ // SecureChannel is the same as the Certificate used to create the original SecureChannel.
1311
+ if (session.status === "active") {
1312
+ if (session.channel.channelId !== channel.channelId) {
1313
+ warningLog(" Session ", session.sessionName, " is being transferred from channel", chalk.cyan(session.channel.channelId.toString()), " to channel ", chalk.cyan(channel.channelId.toString()));
1314
+ // session is being reassigned to a new Channel,
1315
+ // we shall verify that the certificate used to create the Session is the same as the current
1316
+ // channel certificate.
1317
+ const old_channel_cert_thumbprint = thumbprint(session.channel.clientCertificate);
1318
+ const new_channel_cert_thumbprint = thumbprint(channel.clientCertificate);
1319
+ if (old_channel_cert_thumbprint !== new_channel_cert_thumbprint) {
1320
+ return rejectConnection(this, node_opcua_status_code_1.StatusCodes.BadNoValidCertificates); // not sure about this code !
1321
+ }
1322
+ // ... In addition the Server shall verify that the Client supplied a UserIdentityToken that is
1323
+ // identical to the token currently associated with the Session reassign session to new channel.
1324
+ if (!sameIdentityToken(session.userIdentityToken, request.userIdentityToken)) {
1325
+ return rejectConnection(this, node_opcua_status_code_1.StatusCodes.BadIdentityChangeNotSupported); // not sure about this code !
1326
+ }
1327
+ }
1328
+ moveSessionToChannel(session, channel);
1329
+ }
1330
+ else if (session.status === "screwed") {
1331
+ // session has been used before being activated => this should be detected and session should be dismissed.
1332
+ return rejectConnection(this, node_opcua_status_code_1.StatusCodes.BadSessionClosed);
1333
+ }
1334
+ else if (session.status === "closed") {
1335
+ warningLog(chalk.yellow.bold(" Bad Session Closed in _on_ActivateSessionRequest"), authenticationToken.toString());
1336
+ return rejectConnection(this, node_opcua_status_code_1.StatusCodes.BadSessionClosed);
1337
+ }
1338
+ // verify clientSignature provided by the client
1339
+ if (!this.verifyClientSignature(session, channel, request.clientSignature)) {
1340
+ return rejectConnection(this, node_opcua_status_code_1.StatusCodes.BadApplicationSignatureInvalid);
1341
+ }
1342
+ // userIdentityToken may be missing , assume anonymous access then
1343
+ request.userIdentityToken = request.userIdentityToken || createAnonymousIdentityToken(session.endpoint);
1344
+ // check request.userIdentityToken is correct ( expected type and correctly formed)
1345
+ this.isValidUserIdentityToken(channel, session, request.userIdentityToken, request.userTokenSignature, session.endpoint, (err, statusCode) => {
1346
+ if (statusCode !== node_opcua_status_code_1.StatusCodes.Good) {
1347
+ /* istanbul ignore next */
1348
+ if (!(statusCode && statusCode instanceof node_opcua_status_code_1.StatusCode)) {
1349
+ return rejectConnection(this, node_opcua_status_code_1.StatusCodes.BadCertificateInvalid);
1350
+ }
1351
+ return rejectConnection(this, statusCode);
1352
+ }
1353
+ session.userIdentityToken = request.userIdentityToken;
1354
+ // check if user access is granted
1355
+ this.isUserAuthorized(channel, session, request.userIdentityToken, (err1, authorized) => {
1356
+ /* istanbul ignore next */
1357
+ if (err1) {
1358
+ return rejectConnection(this, node_opcua_status_code_1.StatusCodes.BadInternalError);
1359
+ }
1360
+ if (!authorized) {
1361
+ return rejectConnection(this, node_opcua_status_code_1.StatusCodes.BadUserAccessDenied);
1362
+ }
1363
+ else {
1364
+ // extract : OPC UA part 4 - 5.6.3
1365
+ // Once used, a serverNonce cannot be used again. For that reason, the Server returns a new
1366
+ // serverNonce each time the ActivateSession Service is called.
1367
+ session.nonce = this.makeServerNonce();
1368
+ session.status = "active";
1369
+ response = new node_opcua_service_session_1.ActivateSessionResponse({ serverNonce: session.nonce });
1370
+ channel.send_response("MSG", response, message);
1371
+ const userIdentityTokenPasswordRemoved = (userIdentityToken) => {
1372
+ const a = userIdentityToken.clone();
1373
+ // remove password
1374
+ a.password = "*************";
1375
+ return a;
1376
+ };
1377
+ // send OPCUA Event Notification
1378
+ // see part 5 : 6.4.3 AuditEventType
1379
+ // 6.4.7 AuditSessionEventType
1380
+ // 6.4.10 AuditActivateSessionEventType
1381
+ (0, node_opcua_assert_1.assert)(session.nodeId); // sessionId
1382
+ // xx assert(session.channel.clientCertificate instanceof Buffer);
1383
+ (0, node_opcua_assert_1.assert)(session.sessionTimeout > 0);
1384
+ if (this.isAuditing) {
1385
+ this.raiseEvent("AuditActivateSessionEventType", {
1386
+ /* part 5 - 6.4.3 AuditEventType */
1387
+ actionTimeStamp: { dataType: "DateTime", value: new Date() },
1388
+ status: { dataType: "Boolean", value: true },
1389
+ serverId: { dataType: "String", value: "" },
1390
+ // ClientAuditEntryId contains the human-readable AuditEntryId defined in Part 3.
1391
+ clientAuditEntryId: { dataType: "String", value: "" },
1392
+ // The ClientUserId identifies the user of the client requesting an action.
1393
+ // The ClientUserId can be obtained from the UserIdentityToken passed in the
1394
+ // ActivateSession call.
1395
+ clientUserId: { dataType: "String", value: "cc" },
1396
+ sourceName: { dataType: "String", value: "Session/ActivateSession" },
1397
+ /* part 5 - 6.4.7 AuditSessionEventType */
1398
+ sessionId: { dataType: "NodeId", value: session.nodeId },
1399
+ /* part 5 - 6.4.10 AuditActivateSessionEventType */
1400
+ clientSoftwareCertificates: {
1401
+ arrayType: node_opcua_variant_2.VariantArrayType.Array,
1402
+ dataType: "ExtensionObject" /* SignedSoftwareCertificate */,
1403
+ value: []
1404
+ },
1405
+ // UserIdentityToken reflects the userIdentityToken parameter of the ActivateSession
1406
+ // Service call.
1407
+ // For Username/Password tokens the password should NOT be included.
1408
+ userIdentityToken: {
1409
+ dataType: "ExtensionObject" /* UserIdentityToken */,
1410
+ value: userIdentityTokenPasswordRemoved(session.userIdentityToken)
1411
+ },
1412
+ // SecureChannelId shall uniquely identify the SecureChannel. The application shall
1413
+ // use the same identifier in all AuditEvents related to the Session Service Set
1414
+ // (AuditCreateSessionEventType, AuditActivateSessionEventType and their subtypes) and
1415
+ // the SecureChannel Service Set (AuditChannelEventType and its subtypes).
1416
+ secureChannelId: { dataType: "String", value: session.channel.channelId.toString() }
1417
+ });
1418
+ }
1419
+ this.emit("session_activated", session, userIdentityTokenPasswordRemoved);
1420
+ }
1421
+ });
1422
+ });
1423
+ }
1424
+ prepare(message, channel) {
1425
+ const request = message.request;
1426
+ // --- check that session is correct
1427
+ const authenticationToken = request.requestHeader.authenticationToken;
1428
+ const session = this.getSession(authenticationToken, /*activeOnly*/ true);
1429
+ if (!session) {
1430
+ message.session_statusCode = node_opcua_status_code_1.StatusCodes.BadSessionIdInvalid;
1431
+ return;
1432
+ }
1433
+ message.session = session;
1434
+ // --- check that provided session matches session attached to channel
1435
+ if (channel.channelId !== session.channelId) {
1436
+ if (!(request instanceof node_opcua_service_session_1.ActivateSessionRequest)) {
1437
+ errorLog(chalk.red.bgWhite("ERROR: channel.channelId !== session.channelId on processing request " + request.constructor.name), channel.channelId, session.channelId);
1438
+ }
1439
+ message.session_statusCode = node_opcua_status_code_1.StatusCodes.BadSecureChannelIdInvalid;
1440
+ }
1441
+ else if (channel_has_session(channel, session)) {
1442
+ message.session_statusCode = node_opcua_status_code_1.StatusCodes.Good;
1443
+ }
1444
+ else {
1445
+ // session ma y have been moved to a different channel
1446
+ message.session_statusCode = node_opcua_status_code_1.StatusCodes.BadSecureChannelIdInvalid;
1447
+ }
1448
+ }
1449
+ /**
1450
+ * ensure that action is performed on a valid session object,
1451
+ * @method _apply_on_SessionObject
1452
+ * @param ResponseClass the constructor of the response Class
1453
+ * @param message
1454
+ * @param channel
1455
+ * @param actionToPerform
1456
+ * @param actionToPerform.session {ServerSession}
1457
+ * @param actionToPerform.sendResponse
1458
+ * @param actionToPerform.sendResponse.response
1459
+ * @param actionToPerform.sendError
1460
+ * @param actionToPerform.sendError.statusCode
1461
+ * @param actionToPerform.sendError.diagnostics
1462
+ *
1463
+ * @private
1464
+ */
1465
+ _apply_on_SessionObject(ResponseClass, message, channel, actionToPerform) {
1466
+ return __awaiter(this, void 0, void 0, function* () {
1467
+ (0, node_opcua_assert_1.assert)(typeof actionToPerform === "function");
1468
+ function sendResponse(response1) {
1469
+ try {
1470
+ (0, node_opcua_assert_1.assert)(response1 instanceof ResponseClass || response1 instanceof node_opcua_types_1.ServiceFault);
1471
+ if (message.session) {
1472
+ const counterName = ResponseClass.name.replace("Response", "");
1473
+ message.session.incrementRequestTotalCounter(counterName);
1474
+ }
1475
+ return channel.send_response("MSG", response1, message);
1476
+ }
1477
+ catch (err) {
1478
+ warningLog(err);
1479
+ // istanbul ignore next
1480
+ if (err instanceof Error) {
1481
+ // istanbul ignore next
1482
+ errorLog("Internal error in issuing response\nplease contact support@sterfive.com", message.request.toString(), "\n", response1.toString());
1483
+ }
1484
+ // istanbul ignore next
1485
+ throw err;
1486
+ }
1487
+ }
1488
+ function sendError(statusCode) {
1489
+ if (message.session) {
1490
+ message.session.incrementRequestErrorCounter(ResponseClass.name.replace("Response", ""));
1491
+ }
1492
+ return g_sendError(channel, message, ResponseClass, statusCode);
1493
+ }
1494
+ let response;
1495
+ /* istanbul ignore next */
1496
+ if (!message.session || message.session_statusCode !== node_opcua_status_code_1.StatusCodes.Good) {
1497
+ const errMessage = "INVALID SESSION !! ";
1498
+ response = new ResponseClass({ responseHeader: { serviceResult: message.session_statusCode } });
1499
+ debugLog(chalk.red.bold(errMessage), chalk.yellow(message.session_statusCode.toString()), response.constructor.name);
1500
+ return sendResponse(response);
1501
+ }
1502
+ (0, node_opcua_assert_1.assert)(message.session_statusCode === node_opcua_status_code_1.StatusCodes.Good);
1503
+ // OPC UA Specification 1.02 part 4 page 26
1504
+ // When a Session is terminated, all outstanding requests on the Session are aborted and
1505
+ // Bad_SessionClosed StatusCodes are returned to the Client. In addition, the Server deletes the entry
1506
+ // for the Client from its SessionDiagnostics Array Variable and notifies any other Clients who were
1507
+ // subscribed to this entry.
1508
+ if (message.session.status === "closed") {
1509
+ // note : use StatusCodes.BadSessionClosed , for pending message for this session
1510
+ return sendError(node_opcua_status_code_1.StatusCodes.BadSessionIdInvalid);
1511
+ }
1512
+ if (message.session.status === "new") {
1513
+ // mark session as being screwed ! so it cannot be activated anymore
1514
+ message.session.status = "screwed";
1515
+ return sendError(node_opcua_status_code_1.StatusCodes.BadSessionNotActivated);
1516
+ }
1517
+ if (message.session.status !== "active") {
1518
+ // mark session as being screwed ! so it cannot be activated anymore
1519
+ message.session.status = "screwed";
1520
+ // note : use StatusCodes.BadSessionClosed , for pending message for this session
1521
+ return sendError(node_opcua_status_code_1.StatusCodes.BadSessionIdInvalid);
1522
+ }
1523
+ // lets also reset the session watchdog so it doesn't
1524
+ // (Sessions are terminated by the Server automatically if the Client fails to issue a Service
1525
+ // request on the Session within the timeout period negotiated by the Server in the
1526
+ // CreateSession Service response. )
1527
+ if (message.session.keepAlive) {
1528
+ (0, node_opcua_assert_1.assert)(typeof message.session.keepAlive === "function");
1529
+ message.session.keepAlive();
1530
+ }
1531
+ message.session.incrementTotalRequestCount();
1532
+ yield actionToPerform(message.session, sendResponse, sendError);
1533
+ });
1534
+ }
1535
+ _apply_on_Subscription(ResponseClass, message, channel, actionToPerform) {
1536
+ return __awaiter(this, void 0, void 0, function* () {
1537
+ (0, node_opcua_assert_1.assert)(typeof actionToPerform === "function");
1538
+ const request = message.request;
1539
+ (0, node_opcua_assert_1.assert)(Object.prototype.hasOwnProperty.call(request, "subscriptionId"));
1540
+ this._apply_on_SessionObject(ResponseClass, message, channel, (session, sendResponse, sendError) => __awaiter(this, void 0, void 0, function* () {
1541
+ const subscription = session.getSubscription(request.subscriptionId);
1542
+ if (!subscription) {
1543
+ return sendError(node_opcua_status_code_1.StatusCodes.BadSubscriptionIdInvalid);
1544
+ }
1545
+ subscription.resetLifeTimeAndKeepAliveCounters();
1546
+ yield actionToPerform(session, subscription, sendResponse, sendError);
1547
+ }));
1548
+ });
1549
+ }
1550
+ _apply_on_SubscriptionIds(ResponseClass, message, channel, actionToPerform) {
1551
+ (0, node_opcua_assert_1.assert)(typeof actionToPerform === "function");
1552
+ const request = message.request;
1553
+ (0, node_opcua_assert_1.assert)(Object.prototype.hasOwnProperty.call(request, "subscriptionIds"));
1554
+ this._apply_on_SessionObject(ResponseClass, message, channel, (session, sendResponse, sendError) => __awaiter(this, void 0, void 0, function* () {
1555
+ const subscriptionIds = request.subscriptionIds;
1556
+ if (!request.subscriptionIds || request.subscriptionIds.length === 0) {
1557
+ return sendError(node_opcua_status_code_1.StatusCodes.BadNothingToDo);
1558
+ }
1559
+ const results = subscriptionIds.map((subscriptionId) => actionToPerform(session, subscriptionId));
1560
+ // resolve potential pending promises ....
1561
+ for (let i = 0; i < results.length; i++) {
1562
+ if (results[i].then) {
1563
+ results[i] = yield results[i];
1564
+ }
1565
+ }
1566
+ const response = new ResponseClass({
1567
+ responseHeader: {
1568
+ serviceResult: request.subscriptionIds.length > this.engine.serverCapabilities.maxSubscriptionsPerSession
1569
+ ? node_opcua_status_code_1.StatusCodes.BadTooManyOperations
1570
+ : node_opcua_status_code_1.StatusCodes.Good
1571
+ },
1572
+ results
1573
+ });
1574
+ sendResponse(response);
1575
+ }));
1576
+ }
1577
+ _apply_on_Subscriptions(ResponseClass, message, channel, actionToPerform) {
1578
+ this._apply_on_SubscriptionIds(ResponseClass, message, channel, (session, subscriptionId) => __awaiter(this, void 0, void 0, function* () {
1579
+ /* istanbul ignore next */
1580
+ if (isSubscriptionIdInvalid(subscriptionId)) {
1581
+ return node_opcua_status_code_1.StatusCodes.BadSubscriptionIdInvalid;
1582
+ }
1583
+ const subscription = session.getSubscription(subscriptionId);
1584
+ if (!subscription) {
1585
+ return node_opcua_status_code_1.StatusCodes.BadSubscriptionIdInvalid;
1586
+ }
1587
+ return actionToPerform(session, subscription);
1588
+ }));
1589
+ }
1590
+ _closeSession(authenticationToken, deleteSubscriptions, reason) {
1591
+ return __awaiter(this, void 0, void 0, function* () {
1592
+ if (deleteSubscriptions && this.options.onDeleteMonitoredItem) {
1593
+ const session = this.getSession(authenticationToken);
1594
+ if (session) {
1595
+ const subscriptions = session.publishEngine.subscriptions;
1596
+ for (const subscription of subscriptions) {
1597
+ yield subscription.applyOnMonitoredItem(this.options.onDeleteMonitoredItem.bind(null, subscription));
1598
+ }
1599
+ }
1600
+ }
1601
+ yield this.engine.closeSession(authenticationToken, deleteSubscriptions, reason);
1602
+ });
1603
+ }
1604
+ /**
1605
+ * @method _on_CloseSessionRequest
1606
+ * @param message
1607
+ * @param channel
1608
+ * @private
1609
+ */
1610
+ _on_CloseSessionRequest(message, channel) {
1611
+ const request = message.request;
1612
+ (0, node_opcua_assert_1.assert)(request instanceof node_opcua_service_session_1.CloseSessionRequest);
1613
+ let response;
1614
+ message.session_statusCode = node_opcua_status_code_1.StatusCodes.Good;
1615
+ function sendError(statusCode) {
1616
+ return g_sendError(channel, message, node_opcua_service_session_1.CloseSessionResponse, statusCode);
1617
+ }
1618
+ function sendResponse(response1) {
1619
+ channel.send_response("MSG", response1, message);
1620
+ }
1621
+ // do not use _apply_on_SessionObject
1622
+ // this._apply_on_SessionObject(CloseSessionResponse, message, channel, function (session) {
1623
+ // });
1624
+ const session = message.session;
1625
+ if (!session) {
1626
+ return sendError(node_opcua_status_code_1.StatusCodes.BadSessionIdInvalid);
1627
+ }
1628
+ // session has been created but not activated !
1629
+ const wasNotActivated = session.status === "new";
1630
+ (() => __awaiter(this, void 0, void 0, function* () {
1631
+ yield this._closeSession(request.requestHeader.authenticationToken, request.deleteSubscriptions, "CloseSession");
1632
+ // if (false && wasNotActivated) {
1633
+ // return sendError(StatusCodes.BadSessionNotActivated);
1634
+ // }
1635
+ response = new node_opcua_service_session_1.CloseSessionResponse({});
1636
+ sendResponse(response);
1637
+ }))();
1638
+ }
1639
+ // browse services
1640
+ /**
1641
+ * @method _on_BrowseRequest
1642
+ * @param message
1643
+ * @param channel
1644
+ * @private
1645
+ */
1646
+ _on_BrowseRequest(message, channel) {
1647
+ const request = message.request;
1648
+ (0, node_opcua_assert_1.assert)(request instanceof node_opcua_service_browse_1.BrowseRequest);
1649
+ const diagnostic = {};
1650
+ this._apply_on_SessionObject(node_opcua_service_browse_1.BrowseResponse, message, channel, (session, sendResponse, sendError) => {
1651
+ let response;
1652
+ // test view
1653
+ if (request.view && !request.view.viewId.isEmpty()) {
1654
+ let theView = this.engine.addressSpace.findNode(request.view.viewId);
1655
+ if (theView && theView.nodeClass !== node_opcua_data_model_1.NodeClass.View) {
1656
+ // Error: theView is not a View
1657
+ diagnostic.localizedText = { text: "Expecting a view here" };
1658
+ theView = null;
1659
+ }
1660
+ if (!theView) {
1661
+ return sendError(node_opcua_status_code_1.StatusCodes.BadViewIdUnknown);
1662
+ }
1663
+ }
1664
+ if (!request.nodesToBrowse || request.nodesToBrowse.length === 0) {
1665
+ return sendError(node_opcua_status_code_1.StatusCodes.BadNothingToDo);
1666
+ }
1667
+ if (this.engine.serverCapabilities.operationLimits.maxNodesPerBrowse > 0) {
1668
+ if (request.nodesToBrowse.length > this.engine.serverCapabilities.operationLimits.maxNodesPerBrowse) {
1669
+ return sendError(node_opcua_status_code_1.StatusCodes.BadTooManyOperations);
1670
+ }
1671
+ }
1672
+ // limit results to requestedMaxReferencesPerNode further so it never exceed a too big number
1673
+ const requestedMaxReferencesPerNode = Math.min(9876, request.requestedMaxReferencesPerNode);
1674
+ (0, node_opcua_assert_1.assert)(request.nodesToBrowse[0].schema.name === "BrowseDescription");
1675
+ const context = new node_opcua_address_space_1.SessionContext({ session, server: this });
1676
+ const f = (0, util_1.callbackify)(this.engine.browseWithAutomaticExpansion).bind(this.engine);
1677
+ f(request.nodesToBrowse, context, (err, results) => {
1678
+ // istanbul ignore next
1679
+ if (!results) {
1680
+ throw new Error("internal error : " + (err === null || err === void 0 ? void 0 : err.message));
1681
+ }
1682
+ (0, node_opcua_assert_1.assert)(results[0].schema.name === "BrowseResult");
1683
+ // handle continuation point and requestedMaxReferencesPerNode
1684
+ const maxBrowseContinuationPoints = this.engine.serverCapabilities.maxBrowseContinuationPoints;
1685
+ results = results.map((result) => {
1686
+ (0, node_opcua_assert_1.assert)(!result.continuationPoint);
1687
+ // istanbul ignore next
1688
+ if (!session.continuationPointManager) {
1689
+ return new node_opcua_types_1.BrowseResult({ statusCode: node_opcua_status_code_1.StatusCodes.BadNoContinuationPoints });
1690
+ }
1691
+ if (session.continuationPointManager.hasReachedMaximum(maxBrowseContinuationPoints)) {
1692
+ return new node_opcua_types_1.BrowseResult({ statusCode: node_opcua_status_code_1.StatusCodes.BadNoContinuationPoints });
1693
+ }
1694
+ const truncatedResult = session.continuationPointManager.registerReferences(requestedMaxReferencesPerNode, result.references || [], { continuationPoint: null });
1695
+ let { statusCode } = truncatedResult;
1696
+ const { continuationPoint, values } = truncatedResult;
1697
+ statusCode = result.statusCode;
1698
+ return new node_opcua_types_1.BrowseResult({
1699
+ statusCode,
1700
+ continuationPoint,
1701
+ references: values
1702
+ });
1703
+ });
1704
+ response = new node_opcua_service_browse_1.BrowseResponse({
1705
+ diagnosticInfos: undefined,
1706
+ results
1707
+ });
1708
+ sendResponse(response);
1709
+ });
1710
+ });
1711
+ }
1712
+ /**
1713
+ * @method _on_BrowseNextRequest
1714
+ * @param message
1715
+ * @param channel
1716
+ * @private
1717
+ */
1718
+ _on_BrowseNextRequest(message, channel) {
1719
+ const request = message.request;
1720
+ (0, node_opcua_assert_1.assert)(request instanceof node_opcua_service_browse_1.BrowseNextRequest);
1721
+ this._apply_on_SessionObject(node_opcua_service_browse_1.BrowseNextResponse, message, channel, (session, sendResponse, sendError) => {
1722
+ if (!request.continuationPoints || request.continuationPoints.length === 0) {
1723
+ return sendError(node_opcua_status_code_1.StatusCodes.BadNothingToDo);
1724
+ }
1725
+ const results = request.continuationPoints
1726
+ .map((continuationPoint, index) => session.continuationPointManager.getNextReferences(0, {
1727
+ continuationPoint,
1728
+ index,
1729
+ releaseContinuationPoints: request.releaseContinuationPoints
1730
+ }))
1731
+ .map((r) => ({
1732
+ continuationPoint: r.continuationPoint,
1733
+ references: r.values,
1734
+ statusCode: r.statusCode
1735
+ }));
1736
+ const response = new node_opcua_service_browse_1.BrowseNextResponse({
1737
+ diagnosticInfos: undefined,
1738
+ results
1739
+ });
1740
+ sendResponse(response);
1741
+ });
1742
+ }
1743
+ // read services
1744
+ _on_ReadRequest(message, channel) {
1745
+ const request = message.request;
1746
+ (0, node_opcua_assert_1.assert)(request instanceof node_opcua_service_read_1.ReadRequest);
1747
+ this._apply_on_SessionObject(node_opcua_service_read_1.ReadResponse, message, channel, (session, sendResponse, sendError) => {
1748
+ const context = new node_opcua_address_space_1.SessionContext({ session, server: this });
1749
+ let response;
1750
+ let results = [];
1751
+ const timestampsToReturn = request.timestampsToReturn;
1752
+ if (timestampsToReturn === node_opcua_service_read_1.TimestampsToReturn.Invalid) {
1753
+ return sendError(node_opcua_status_code_1.StatusCodes.BadTimestampsToReturnInvalid);
1754
+ }
1755
+ if (request.maxAge < 0) {
1756
+ return sendError(node_opcua_status_code_1.StatusCodes.BadMaxAgeInvalid);
1757
+ }
1758
+ request.nodesToRead = request.nodesToRead || [];
1759
+ if (!request.nodesToRead || request.nodesToRead.length <= 0) {
1760
+ return sendError(node_opcua_status_code_1.StatusCodes.BadNothingToDo);
1761
+ }
1762
+ (0, node_opcua_assert_1.assert)(request.nodesToRead[0].schema.name === "ReadValueId");
1763
+ // limit size of nodesToRead array to maxNodesPerRead
1764
+ if (this.engine.serverCapabilities.operationLimits.maxNodesPerRead > 0) {
1765
+ if (request.nodesToRead.length > this.engine.serverCapabilities.operationLimits.maxNodesPerRead) {
1766
+ return sendError(node_opcua_status_code_1.StatusCodes.BadTooManyOperations);
1767
+ }
1768
+ }
1769
+ // proceed with registered nodes alias resolution
1770
+ for (const nodeToRead of request.nodesToRead) {
1771
+ nodeToRead.nodeId = session.resolveRegisteredNode(nodeToRead.nodeId);
1772
+ }
1773
+ // ask for a refresh of asynchronous variables
1774
+ this.engine.refreshValues(request.nodesToRead, request.maxAge, (err) => {
1775
+ (0, node_opcua_assert_1.assert)(!err, " error not handled here , fix me");
1776
+ results = this.engine.read(context, request);
1777
+ (0, node_opcua_assert_1.assert)(results[0].schema.name === "DataValue");
1778
+ (0, node_opcua_assert_1.assert)(results.length === request.nodesToRead.length);
1779
+ response = new node_opcua_service_read_1.ReadResponse({
1780
+ diagnosticInfos: undefined,
1781
+ results: undefined
1782
+ });
1783
+ // set it here for performance
1784
+ response.results = results;
1785
+ (0, node_opcua_assert_1.assert)(response.diagnosticInfos.length === 0);
1786
+ sendResponse(response);
1787
+ });
1788
+ });
1789
+ }
1790
+ // read services
1791
+ _on_HistoryReadRequest(message, channel) {
1792
+ const request = message.request;
1793
+ (0, node_opcua_assert_1.assert)(request instanceof node_opcua_service_history_1.HistoryReadRequest);
1794
+ this._apply_on_SessionObject(node_opcua_service_history_1.HistoryReadResponse, message, channel, (session, sendResponse, sendError) => {
1795
+ let response;
1796
+ const timestampsToReturn = request.timestampsToReturn;
1797
+ if (timestampsToReturn === node_opcua_service_read_1.TimestampsToReturn.Invalid) {
1798
+ return sendError(node_opcua_status_code_1.StatusCodes.BadTimestampsToReturnInvalid);
1799
+ }
1800
+ request.nodesToRead = request.nodesToRead || [];
1801
+ if (!request.nodesToRead || request.nodesToRead.length <= 0) {
1802
+ return sendError(node_opcua_status_code_1.StatusCodes.BadNothingToDo);
1803
+ }
1804
+ (0, node_opcua_assert_1.assert)(request.nodesToRead[0].schema.name === "HistoryReadValueId");
1805
+ // limit size of nodesToRead array to maxNodesPerRead
1806
+ if (this.engine.serverCapabilities.operationLimits.maxNodesPerRead > 0) {
1807
+ if (request.nodesToRead.length > this.engine.serverCapabilities.operationLimits.maxNodesPerRead) {
1808
+ return sendError(node_opcua_status_code_1.StatusCodes.BadTooManyOperations);
1809
+ }
1810
+ }
1811
+ // todo : handle
1812
+ if (this.engine.serverCapabilities.operationLimits.maxNodesPerHistoryReadData > 0) {
1813
+ if (request.nodesToRead.length > this.engine.serverCapabilities.operationLimits.maxNodesPerHistoryReadData) {
1814
+ return sendError(node_opcua_status_code_1.StatusCodes.BadTooManyOperations);
1815
+ }
1816
+ }
1817
+ if (this.engine.serverCapabilities.operationLimits.maxNodesPerHistoryReadEvents > 0) {
1818
+ if (request.nodesToRead.length > this.engine.serverCapabilities.operationLimits.maxNodesPerHistoryReadEvents) {
1819
+ return sendError(node_opcua_status_code_1.StatusCodes.BadTooManyOperations);
1820
+ }
1821
+ }
1822
+ const context = new node_opcua_address_space_1.SessionContext({ session, server: this });
1823
+ // ask for a refresh of asynchronous variables
1824
+ this.engine.refreshValues(request.nodesToRead, 0, (err) => {
1825
+ (0, node_opcua_assert_1.assert)(!err, " error not handled here , fix me"); // TODO
1826
+ this.engine.historyRead(context, request, (err1, results) => {
1827
+ if (err1) {
1828
+ return sendError(node_opcua_status_code_1.StatusCodes.BadHistoryOperationInvalid);
1829
+ }
1830
+ if (!results) {
1831
+ return sendError(node_opcua_status_code_1.StatusCodes.BadHistoryOperationInvalid);
1832
+ }
1833
+ (0, node_opcua_assert_1.assert)(results[0].schema.name === "HistoryReadResult");
1834
+ (0, node_opcua_assert_1.assert)(results.length === request.nodesToRead.length);
1835
+ response = new node_opcua_service_history_1.HistoryReadResponse({
1836
+ diagnosticInfos: undefined,
1837
+ results
1838
+ });
1839
+ (0, node_opcua_assert_1.assert)(response.diagnosticInfos.length === 0);
1840
+ sendResponse(response);
1841
+ });
1842
+ });
1843
+ });
1844
+ }
1845
+ /*
1846
+ // write services
1847
+ // OPCUA Specification 1.02 Part 3 : 5.10.4 Write
1848
+ // This Service is used to write values to one or more Attributes of one or more Nodes. For constructed
1849
+ // Attribute values whose elements are indexed, such as an array, this Service allows Clients to write
1850
+ // the entire set of indexed values as a composite, to write individual elements or to write ranges of
1851
+ // elements of the composite.
1852
+ // The values are written to the data source, such as a device, and the Service does not return until it writes
1853
+ // the values or determines that the value cannot be written. In certain cases, the Server will successfully
1854
+ // to an intermediate system or Server, and will not know if the data source was updated properly. In these cases,
1855
+ // the Server should report a success code that indicates that the write was not verified.
1856
+ // In the cases where the Server is able to verify that it has successfully written to the data source,
1857
+ // it reports an unconditional success.
1858
+ */
1859
+ _on_WriteRequest(message, channel) {
1860
+ const request = message.request;
1861
+ (0, node_opcua_assert_1.assert)(request instanceof node_opcua_service_write_1.WriteRequest);
1862
+ (0, node_opcua_assert_1.assert)(!request.nodesToWrite || Array.isArray(request.nodesToWrite));
1863
+ this._apply_on_SessionObject(node_opcua_service_write_1.WriteResponse, message, channel, (session, sendResponse, sendError) => {
1864
+ let response;
1865
+ if (!request.nodesToWrite || request.nodesToWrite.length === 0) {
1866
+ return sendError(node_opcua_status_code_1.StatusCodes.BadNothingToDo);
1867
+ }
1868
+ if (this.engine.serverCapabilities.operationLimits.maxNodesPerWrite > 0) {
1869
+ if (request.nodesToWrite.length > this.engine.serverCapabilities.operationLimits.maxNodesPerWrite) {
1870
+ return sendError(node_opcua_status_code_1.StatusCodes.BadTooManyOperations);
1871
+ }
1872
+ }
1873
+ // proceed with registered nodes alias resolution
1874
+ for (const nodeToWrite of request.nodesToWrite) {
1875
+ nodeToWrite.nodeId = session.resolveRegisteredNode(nodeToWrite.nodeId);
1876
+ }
1877
+ const context = new node_opcua_address_space_1.SessionContext({ session, server: this });
1878
+ (0, node_opcua_assert_1.assert)(request.nodesToWrite[0].schema.name === "WriteValue");
1879
+ this.engine.write(context, request.nodesToWrite, (err, results) => {
1880
+ if (err) {
1881
+ errorLog(err);
1882
+ return sendError(node_opcua_status_code_1.StatusCodes.BadInternalError);
1883
+ }
1884
+ (0, node_opcua_assert_1.assert)(Array.isArray(results));
1885
+ (0, node_opcua_assert_1.assert)(results.length === request.nodesToWrite.length);
1886
+ response = new node_opcua_service_write_1.WriteResponse({
1887
+ diagnosticInfos: undefined,
1888
+ results
1889
+ });
1890
+ sendResponse(response);
1891
+ });
1892
+ });
1893
+ }
1894
+ // subscription services
1895
+ _on_CreateSubscriptionRequest(message, channel) {
1896
+ const engine = this.engine;
1897
+ const addressSpace = engine.addressSpace;
1898
+ const request = message.request;
1899
+ (0, node_opcua_assert_1.assert)(request instanceof node_opcua_service_subscription_1.CreateSubscriptionRequest);
1900
+ this._apply_on_SessionObject(node_opcua_service_subscription_1.CreateSubscriptionResponse, message, channel, (session, sendResponse, sendError) => {
1901
+ const context = new node_opcua_address_space_1.SessionContext({ session, server: this });
1902
+ if (session.currentSubscriptionCount >= this.engine.serverCapabilities.maxSubscriptionsPerSession) {
1903
+ return sendError(node_opcua_status_code_1.StatusCodes.BadTooManySubscriptions);
1904
+ }
1905
+ if (this.currentSubscriptionCount >= this.engine.serverCapabilities.maxSubscriptions) {
1906
+ return sendError(node_opcua_status_code_1.StatusCodes.BadTooManySubscriptions);
1907
+ }
1908
+ const subscription = session.createSubscription(request);
1909
+ subscription.on("monitoredItem", (monitoredItem) => {
1910
+ prepareMonitoredItem(context, addressSpace, monitoredItem);
1911
+ });
1912
+ const response = new node_opcua_service_subscription_1.CreateSubscriptionResponse({
1913
+ revisedLifetimeCount: subscription.lifeTimeCount,
1914
+ revisedMaxKeepAliveCount: subscription.maxKeepAliveCount,
1915
+ revisedPublishingInterval: subscription.publishingInterval,
1916
+ subscriptionId: subscription.id
1917
+ });
1918
+ sendResponse(response);
1919
+ });
1920
+ }
1921
+ _on_DeleteSubscriptionsRequest(message, channel) {
1922
+ const request = message.request;
1923
+ (0, node_opcua_assert_1.assert)(request instanceof node_opcua_service_subscription_1.DeleteSubscriptionsRequest);
1924
+ this._apply_on_SubscriptionIds(node_opcua_service_subscription_1.DeleteSubscriptionsResponse, message, channel, (session, subscriptionId) => __awaiter(this, void 0, void 0, function* () {
1925
+ let subscription = this.engine.findOrphanSubscription(subscriptionId);
1926
+ // istanbul ignore next
1927
+ if (subscription) {
1928
+ warningLog("Deleting an orphan subscription", subscriptionId);
1929
+ yield this._beforeDeleteSubscription(subscription);
1930
+ return this.engine.deleteOrphanSubscription(subscription);
1931
+ }
1932
+ subscription = session.getSubscription(subscriptionId);
1933
+ if (subscription) {
1934
+ yield this._beforeDeleteSubscription(subscription);
1935
+ }
1936
+ return session.deleteSubscription(subscriptionId);
1937
+ }));
1938
+ }
1939
+ _on_TransferSubscriptionsRequest(message, channel) {
1940
+ //
1941
+ // sendInitialValue Boolean
1942
+ // A Boolean parameter with the following values:
1943
+ // TRUE the first Publish response(s) after the TransferSubscriptions call shall
1944
+ // contain the current values of all Monitored Items in the Subscription where
1945
+ // the Monitoring Mode is set to Reporting.
1946
+ // FALSE the first Publish response after the TransferSubscriptions call shall contain only the value
1947
+ // changes since the last Publish response was sent.
1948
+ // This parameter only applies to MonitoredItems used for monitoring Attribute changes.
1949
+ //
1950
+ const engine = this.engine;
1951
+ const request = message.request;
1952
+ (0, node_opcua_assert_1.assert)(request instanceof node_opcua_service_subscription_1.TransferSubscriptionsRequest);
1953
+ this._apply_on_SubscriptionIds(node_opcua_service_subscription_1.TransferSubscriptionsResponse, message, channel, (session, subscriptionId) => __awaiter(this, void 0, void 0, function* () { return yield engine.transferSubscription(session, subscriptionId, request.sendInitialValues); }));
1954
+ }
1955
+ _on_CreateMonitoredItemsRequest(message, channel) {
1956
+ const engine = this.engine;
1957
+ const addressSpace = engine.addressSpace;
1958
+ const request = message.request;
1959
+ (0, node_opcua_assert_1.assert)(request instanceof node_opcua_service_subscription_1.CreateMonitoredItemsRequest);
1960
+ this._apply_on_Subscription(node_opcua_service_subscription_1.CreateMonitoredItemsResponse, message, channel, (session, subscription, sendResponse, sendError) => __awaiter(this, void 0, void 0, function* () {
1961
+ const timestampsToReturn = request.timestampsToReturn;
1962
+ if (timestampsToReturn === node_opcua_service_read_1.TimestampsToReturn.Invalid) {
1963
+ return sendError(node_opcua_status_code_1.StatusCodes.BadTimestampsToReturnInvalid);
1964
+ }
1965
+ if (!request.itemsToCreate || request.itemsToCreate.length === 0) {
1966
+ return sendError(node_opcua_status_code_1.StatusCodes.BadNothingToDo);
1967
+ }
1968
+ if (this.engine.serverCapabilities.operationLimits.maxMonitoredItemsPerCall > 0) {
1969
+ if (request.itemsToCreate.length > this.engine.serverCapabilities.operationLimits.maxMonitoredItemsPerCall) {
1970
+ return sendError(node_opcua_status_code_1.StatusCodes.BadTooManyOperations);
1971
+ }
1972
+ }
1973
+ const options = this.options;
1974
+ let results = [];
1975
+ if (options.onCreateMonitoredItem) {
1976
+ const resultsPromise = request.itemsToCreate.map((monitoredItemCreateRequest) => __awaiter(this, void 0, void 0, function* () {
1977
+ const { monitoredItem, createResult } = subscription.preCreateMonitoredItem(addressSpace, timestampsToReturn, monitoredItemCreateRequest);
1978
+ if (monitoredItem) {
1979
+ yield options.onCreateMonitoredItem(subscription, monitoredItem);
1980
+ subscription.postCreateMonitoredItem(monitoredItem, monitoredItemCreateRequest, createResult);
1981
+ }
1982
+ return createResult;
1983
+ }));
1984
+ results = yield Promise.all(resultsPromise);
1985
+ }
1986
+ else {
1987
+ results = request.itemsToCreate.map((monitoredItemCreateRequest) => {
1988
+ const { monitoredItem, createResult } = subscription.preCreateMonitoredItem(addressSpace, timestampsToReturn, monitoredItemCreateRequest);
1989
+ if (monitoredItem) {
1990
+ subscription.postCreateMonitoredItem(monitoredItem, monitoredItemCreateRequest, createResult);
1991
+ }
1992
+ return createResult;
1993
+ });
1994
+ }
1995
+ const response = new node_opcua_service_subscription_1.CreateMonitoredItemsResponse({
1996
+ responseHeader: { serviceResult: node_opcua_status_code_1.StatusCodes.Good },
1997
+ results
1998
+ // ,diagnosticInfos: []
1999
+ });
2000
+ sendResponse(response);
2001
+ }));
2002
+ }
2003
+ _on_ModifySubscriptionRequest(message, channel) {
2004
+ const request = message.request;
2005
+ (0, node_opcua_assert_1.assert)(request instanceof node_opcua_service_subscription_1.ModifySubscriptionRequest);
2006
+ this._apply_on_Subscription(node_opcua_service_subscription_1.ModifySubscriptionResponse, message, channel, (session, subscription, sendResponse, sendError) => __awaiter(this, void 0, void 0, function* () {
2007
+ subscription.modify(request);
2008
+ const response = new node_opcua_service_subscription_1.ModifySubscriptionResponse({
2009
+ revisedLifetimeCount: subscription.lifeTimeCount,
2010
+ revisedMaxKeepAliveCount: subscription.maxKeepAliveCount,
2011
+ revisedPublishingInterval: subscription.publishingInterval
2012
+ });
2013
+ sendResponse(response);
2014
+ }));
2015
+ }
2016
+ _on_ModifyMonitoredItemsRequest(message, channel) {
2017
+ const request = message.request;
2018
+ (0, node_opcua_assert_1.assert)(request instanceof node_opcua_service_subscription_1.ModifyMonitoredItemsRequest);
2019
+ this._apply_on_Subscription(node_opcua_service_subscription_1.ModifyMonitoredItemsResponse, message, channel, (session, subscription, sendResponse, sendError) => __awaiter(this, void 0, void 0, function* () {
2020
+ const timestampsToReturn = request.timestampsToReturn;
2021
+ if (timestampsToReturn === node_opcua_service_read_1.TimestampsToReturn.Invalid) {
2022
+ return sendError(node_opcua_status_code_1.StatusCodes.BadTimestampsToReturnInvalid);
2023
+ }
2024
+ if (!request.itemsToModify || request.itemsToModify.length === 0) {
2025
+ return sendError(node_opcua_status_code_1.StatusCodes.BadNothingToDo);
2026
+ }
2027
+ /* istanbul ignore next */
2028
+ if (this.engine.serverCapabilities.operationLimits.maxMonitoredItemsPerCall > 0) {
2029
+ if (request.itemsToModify.length > this.engine.serverCapabilities.operationLimits.maxMonitoredItemsPerCall) {
2030
+ return sendError(node_opcua_status_code_1.StatusCodes.BadTooManyOperations);
2031
+ }
2032
+ }
2033
+ const itemsToModify = request.itemsToModify; // MonitoredItemModifyRequest
2034
+ function modifyMonitoredItem(item) {
2035
+ const monitoredItemId = item.monitoredItemId;
2036
+ const monitoredItem = subscription.getMonitoredItem(monitoredItemId);
2037
+ if (!monitoredItem) {
2038
+ return new node_opcua_service_subscription_1.MonitoredItemModifyResult({ statusCode: node_opcua_status_code_1.StatusCodes.BadMonitoredItemIdInvalid });
2039
+ }
2040
+ // adjust samplingInterval if === -1
2041
+ if (item.requestedParameters.samplingInterval === -1) {
2042
+ item.requestedParameters.samplingInterval = subscription.publishingInterval;
2043
+ }
2044
+ return monitoredItem.modify(timestampsToReturn, item.requestedParameters);
2045
+ }
2046
+ const results = itemsToModify.map(modifyMonitoredItem);
2047
+ const response = new node_opcua_service_subscription_1.ModifyMonitoredItemsResponse({
2048
+ results
2049
+ });
2050
+ sendResponse(response);
2051
+ }));
2052
+ }
2053
+ _on_PublishRequest(message, channel) {
2054
+ const request = message.request;
2055
+ (0, node_opcua_assert_1.assert)(request instanceof node_opcua_service_subscription_1.PublishRequest);
2056
+ this._apply_on_SessionObject(node_opcua_service_subscription_1.PublishResponse, message, channel, (session, sendResponse, sendError) => {
2057
+ (0, node_opcua_assert_1.assert)(session);
2058
+ (0, node_opcua_assert_1.assert)(session.publishEngine); // server.publishEngine doesn't exists, OPCUAServer has probably shut down already
2059
+ session.publishEngine._on_PublishRequest(request, (_request1, response) => {
2060
+ sendResponse(response);
2061
+ });
2062
+ });
2063
+ }
2064
+ _on_SetPublishingModeRequest(message, channel) {
2065
+ const request = message.request;
2066
+ (0, node_opcua_assert_1.assert)(request instanceof node_opcua_service_subscription_1.SetPublishingModeRequest);
2067
+ const publishingEnabled = request.publishingEnabled;
2068
+ this._apply_on_Subscriptions(node_opcua_service_subscription_1.SetPublishingModeResponse, message, channel, (session, subscription) => __awaiter(this, void 0, void 0, function* () {
2069
+ return subscription.setPublishingMode(publishingEnabled);
2070
+ }));
2071
+ }
2072
+ _on_DeleteMonitoredItemsRequest(message, channel) {
2073
+ const request = message.request;
2074
+ (0, node_opcua_assert_1.assert)(request instanceof node_opcua_service_subscription_1.DeleteMonitoredItemsRequest);
2075
+ this._apply_on_Subscription(node_opcua_service_subscription_1.DeleteMonitoredItemsResponse, message, channel, (session, subscription, sendResponse, sendError) => __awaiter(this, void 0, void 0, function* () {
2076
+ /* istanbul ignore next */
2077
+ if (!request.monitoredItemIds || request.monitoredItemIds.length === 0) {
2078
+ return sendError(node_opcua_status_code_1.StatusCodes.BadNothingToDo);
2079
+ }
2080
+ /* istanbul ignore next */
2081
+ if (this.engine.serverCapabilities.operationLimits.maxMonitoredItemsPerCall > 0) {
2082
+ if (request.monitoredItemIds.length > this.engine.serverCapabilities.operationLimits.maxMonitoredItemsPerCall) {
2083
+ return sendError(node_opcua_status_code_1.StatusCodes.BadTooManyOperations);
2084
+ }
2085
+ }
2086
+ const resultsPromises = request.monitoredItemIds.map((monitoredItemId) => __awaiter(this, void 0, void 0, function* () {
2087
+ if (this.options.onDeleteMonitoredItem) {
2088
+ const monitoredItem = subscription.getMonitoredItem(monitoredItemId);
2089
+ if (monitoredItem) {
2090
+ yield this.options.onDeleteMonitoredItem(subscription, monitoredItem);
2091
+ }
2092
+ }
2093
+ return subscription.removeMonitoredItem(monitoredItemId);
2094
+ }));
2095
+ try {
2096
+ const results = yield Promise.all(resultsPromises);
2097
+ const response = new node_opcua_service_subscription_1.DeleteMonitoredItemsResponse({
2098
+ diagnosticInfos: undefined,
2099
+ results
2100
+ });
2101
+ sendResponse(response);
2102
+ }
2103
+ catch (err) {
2104
+ warningLog(err);
2105
+ return sendError(node_opcua_status_code_1.StatusCodes.BadInternalError);
2106
+ }
2107
+ }));
2108
+ }
2109
+ _on_SetTriggeringRequest(message, channel) {
2110
+ const request = message.request;
2111
+ (0, node_opcua_assert_1.assert)(request instanceof node_opcua_service_subscription_1.SetTriggeringRequest);
2112
+ this._apply_on_Subscription(node_opcua_service_subscription_1.SetTriggeringResponse, message, channel, (session, subscription, sendResponse, sendError) => __awaiter(this, void 0, void 0, function* () {
2113
+ /* */
2114
+ const { triggeringItemId, linksToAdd, linksToRemove } = request;
2115
+ /**
2116
+ * The MaxMonitoredItemsPerCall Property indicates
2117
+ * [...]
2118
+ * • the maximum size of the sum of the linksToAdd and linksToRemove arrays when a
2119
+ * Client calls the SetTriggering Service.
2120
+ *
2121
+ */
2122
+ const maxElements = (linksToAdd ? linksToAdd.length : 0) + (linksToRemove ? linksToRemove.length : 0);
2123
+ if (this.engine.serverCapabilities.operationLimits.maxMonitoredItemsPerCall > 0) {
2124
+ if (maxElements > this.engine.serverCapabilities.operationLimits.maxMonitoredItemsPerCall) {
2125
+ return sendError(node_opcua_status_code_1.StatusCodes.BadTooManyOperations);
2126
+ }
2127
+ }
2128
+ const { addResults, removeResults, statusCode } = subscription.setTriggering(triggeringItemId, linksToAdd, linksToRemove);
2129
+ if (statusCode !== node_opcua_status_code_1.StatusCodes.Good) {
2130
+ const response = new node_opcua_types_1.ServiceFault({ responseHeader: { serviceResult: statusCode } });
2131
+ sendResponse(response);
2132
+ }
2133
+ else {
2134
+ const response = new node_opcua_service_subscription_1.SetTriggeringResponse({
2135
+ responseHeader: { serviceResult: statusCode },
2136
+ addResults,
2137
+ removeResults,
2138
+ addDiagnosticInfos: null,
2139
+ removeDiagnosticInfos: null
2140
+ });
2141
+ sendResponse(response);
2142
+ }
2143
+ }));
2144
+ }
2145
+ _beforeDeleteSubscription(subscription) {
2146
+ return __awaiter(this, void 0, void 0, function* () {
2147
+ if (!this.options.onDeleteMonitoredItem) {
2148
+ return;
2149
+ }
2150
+ yield subscription.applyOnMonitoredItem(this.options.onDeleteMonitoredItem.bind(null, subscription));
2151
+ });
2152
+ }
2153
+ _on_RepublishRequest(message, channel) {
2154
+ const request = message.request;
2155
+ (0, node_opcua_assert_1.assert)(request instanceof node_opcua_service_subscription_1.RepublishRequest);
2156
+ this._apply_on_Subscription(node_opcua_service_subscription_1.RepublishResponse, message, channel, (session, subscription, sendResponse, sendError) => __awaiter(this, void 0, void 0, function* () {
2157
+ // update diagnostic counter
2158
+ subscription.subscriptionDiagnostics.republishRequestCount += 1;
2159
+ subscription.subscriptionDiagnostics.republishMessageRequestCount += 1;
2160
+ const retransmitSequenceNumber = request.retransmitSequenceNumber;
2161
+ const notificationMessage = subscription.getMessageForSequenceNumber(retransmitSequenceNumber);
2162
+ if (!notificationMessage) {
2163
+ return sendError(node_opcua_status_code_1.StatusCodes.BadMessageNotAvailable);
2164
+ }
2165
+ const response = new node_opcua_service_subscription_1.RepublishResponse({
2166
+ notificationMessage,
2167
+ responseHeader: {
2168
+ serviceResult: node_opcua_status_code_1.StatusCodes.Good
2169
+ }
2170
+ });
2171
+ // update diagnostic counter
2172
+ subscription.subscriptionDiagnostics.republishMessageCount += 1;
2173
+ sendResponse(response);
2174
+ }));
2175
+ }
2176
+ // Bad_NothingToDo
2177
+ // Bad_TooManyOperations
2178
+ // Bad_SubscriptionIdInvalid
2179
+ // Bad_MonitoringModeInvalid
2180
+ _on_SetMonitoringModeRequest(message, channel) {
2181
+ const request = message.request;
2182
+ (0, node_opcua_assert_1.assert)(request instanceof node_opcua_service_subscription_1.SetMonitoringModeRequest);
2183
+ this._apply_on_Subscription(node_opcua_service_subscription_1.SetMonitoringModeResponse, message, channel, (session, subscription, sendResponse, sendError) => __awaiter(this, void 0, void 0, function* () {
2184
+ /* istanbul ignore next */
2185
+ if (!request.monitoredItemIds || request.monitoredItemIds.length === 0) {
2186
+ return sendError(node_opcua_status_code_1.StatusCodes.BadNothingToDo);
2187
+ }
2188
+ /* istanbul ignore next */
2189
+ if (this.engine.serverCapabilities.operationLimits.maxMonitoredItemsPerCall > 0) {
2190
+ if (request.monitoredItemIds.length > this.engine.serverCapabilities.operationLimits.maxMonitoredItemsPerCall) {
2191
+ return sendError(node_opcua_status_code_1.StatusCodes.BadTooManyOperations);
2192
+ }
2193
+ }
2194
+ const monitoringMode = request.monitoringMode;
2195
+ if (!isMonitoringModeValid(monitoringMode)) {
2196
+ return sendError(node_opcua_status_code_1.StatusCodes.BadMonitoringModeInvalid);
2197
+ }
2198
+ const results = request.monitoredItemIds.map((monitoredItemId) => {
2199
+ const monitoredItem = subscription.getMonitoredItem(monitoredItemId);
2200
+ if (!monitoredItem) {
2201
+ return node_opcua_status_code_1.StatusCodes.BadMonitoredItemIdInvalid;
2202
+ }
2203
+ monitoredItem.setMonitoringMode(monitoringMode);
2204
+ return node_opcua_status_code_1.StatusCodes.Good;
2205
+ });
2206
+ const response = new node_opcua_service_subscription_1.SetMonitoringModeResponse({
2207
+ results
2208
+ });
2209
+ sendResponse(response);
2210
+ }));
2211
+ }
2212
+ // _on_TranslateBrowsePathsToNodeIds service
2213
+ _on_TranslateBrowsePathsToNodeIdsRequest(message, channel) {
2214
+ const request = message.request;
2215
+ (0, node_opcua_assert_1.assert)(request instanceof node_opcua_service_translate_browse_path_1.TranslateBrowsePathsToNodeIdsRequest);
2216
+ this._apply_on_SessionObject(node_opcua_service_translate_browse_path_1.TranslateBrowsePathsToNodeIdsResponse, message, channel, (session, sendResponse, sendError) => __awaiter(this, void 0, void 0, function* () {
2217
+ if (!request.browsePaths || request.browsePaths.length === 0) {
2218
+ return sendError(node_opcua_status_code_1.StatusCodes.BadNothingToDo);
2219
+ }
2220
+ if (this.engine.serverCapabilities.operationLimits.maxNodesPerTranslateBrowsePathsToNodeIds > 0) {
2221
+ if (request.browsePaths.length >
2222
+ this.engine.serverCapabilities.operationLimits.maxNodesPerTranslateBrowsePathsToNodeIds) {
2223
+ return sendError(node_opcua_status_code_1.StatusCodes.BadTooManyOperations);
2224
+ }
2225
+ }
2226
+ const browsePathsResults = request.browsePaths.map((browsePath) => this.engine.browsePath(browsePath));
2227
+ const response = new node_opcua_service_translate_browse_path_1.TranslateBrowsePathsToNodeIdsResponse({
2228
+ diagnosticInfos: null,
2229
+ results: browsePathsResults
2230
+ });
2231
+ sendResponse(response);
2232
+ }));
2233
+ }
2234
+ // Call Service Result Codes
2235
+ // Symbolic Id Description
2236
+ // Bad_NothingToDo See Table 165 for the description of this result code.
2237
+ // Bad_TooManyOperations See Table 165 for the description of this result code.
2238
+ //
2239
+ _on_CallRequest(message, channel) {
2240
+ const request = message.request;
2241
+ (0, node_opcua_assert_1.assert)(request instanceof node_opcua_service_call_1.CallRequest);
2242
+ this._apply_on_SessionObject(node_opcua_service_call_1.CallResponse, message, channel, (session, sendResponse, sendError) => {
2243
+ let response;
2244
+ if (!request.methodsToCall || request.methodsToCall.length === 0) {
2245
+ return sendError(node_opcua_status_code_1.StatusCodes.BadNothingToDo);
2246
+ }
2247
+ // the MaxNodesPerMethodCall Property indicates the maximum size of the methodsToCall array when
2248
+ // a Client calls the Call Service.
2249
+ let maxNodesPerMethodCall = this.engine.serverCapabilities.operationLimits.maxNodesPerMethodCall;
2250
+ maxNodesPerMethodCall = maxNodesPerMethodCall <= 0 ? 1000 : maxNodesPerMethodCall;
2251
+ if (request.methodsToCall.length > maxNodesPerMethodCall) {
2252
+ return sendError(node_opcua_status_code_1.StatusCodes.BadTooManyOperations);
2253
+ }
2254
+ /* jshint validthis: true */
2255
+ const addressSpace = this.engine.addressSpace;
2256
+ const context = new node_opcua_address_space_1.SessionContext({ session, server: this });
2257
+ async.map(request.methodsToCall, node_opcua_address_space_1.callMethodHelper.bind(null, context, addressSpace), (err, results) => {
2258
+ /* istanbul ignore next */
2259
+ if (err) {
2260
+ errorLog("ERROR in method Call !! ", err);
2261
+ }
2262
+ (0, node_opcua_assert_1.assert)(Array.isArray(results));
2263
+ response = new node_opcua_service_call_1.CallResponse({
2264
+ results: results
2265
+ });
2266
+ filterDiagnosticInfo(request.requestHeader.returnDiagnostics, response);
2267
+ sendResponse(response);
2268
+ });
2269
+ });
2270
+ }
2271
+ _on_RegisterNodesRequest(message, channel) {
2272
+ const request = message.request;
2273
+ (0, node_opcua_assert_1.assert)(request instanceof node_opcua_service_register_node_1.RegisterNodesRequest);
2274
+ this._apply_on_SessionObject(node_opcua_service_register_node_1.RegisterNodesResponse, message, channel, (session, sendResponse, sendError) => {
2275
+ if (!request.nodesToRegister || request.nodesToRegister.length === 0) {
2276
+ return sendError(node_opcua_status_code_1.StatusCodes.BadNothingToDo);
2277
+ }
2278
+ if (this.engine.serverCapabilities.operationLimits.maxNodesPerRegisterNodes > 0) {
2279
+ if (request.nodesToRegister.length > this.engine.serverCapabilities.operationLimits.maxNodesPerRegisterNodes) {
2280
+ return sendError(node_opcua_status_code_1.StatusCodes.BadTooManyOperations);
2281
+ }
2282
+ }
2283
+ // A list of NodeIds which the Client shall use for subsequent access operations. The
2284
+ // size and order of this list matches the size and order of the nodesToRegister
2285
+ // request parameter.
2286
+ // The Server may return the NodeId from the request or a new (an alias) NodeId. It
2287
+ // is recommended that the Server return a numeric NodeIds for aliasing.
2288
+ // In case no optimization is supported for a Node, the Server shall return the
2289
+ // NodeId from the request.
2290
+ const registeredNodeIds = request.nodesToRegister.map((nodeId) => session.registerNode(nodeId));
2291
+ const response = new node_opcua_service_register_node_1.RegisterNodesResponse({
2292
+ registeredNodeIds
2293
+ });
2294
+ sendResponse(response);
2295
+ });
2296
+ }
2297
+ _on_UnregisterNodesRequest(message, channel) {
2298
+ const request = message.request;
2299
+ (0, node_opcua_assert_1.assert)(request instanceof node_opcua_service_register_node_1.UnregisterNodesRequest);
2300
+ this._apply_on_SessionObject(node_opcua_service_register_node_1.UnregisterNodesResponse, message, channel, (session, sendResponse, sendError) => {
2301
+ request.nodesToUnregister = request.nodesToUnregister || [];
2302
+ if (!request.nodesToUnregister || request.nodesToUnregister.length === 0) {
2303
+ return sendError(node_opcua_status_code_1.StatusCodes.BadNothingToDo);
2304
+ }
2305
+ if (this.engine.serverCapabilities.operationLimits.maxNodesPerRegisterNodes > 0) {
2306
+ if (request.nodesToUnregister.length > this.engine.serverCapabilities.operationLimits.maxNodesPerRegisterNodes) {
2307
+ return sendError(node_opcua_status_code_1.StatusCodes.BadTooManyOperations);
2308
+ }
2309
+ }
2310
+ request.nodesToUnregister.map((nodeId) => session.unRegisterNode(nodeId));
2311
+ const response = new node_opcua_service_register_node_1.UnregisterNodesResponse({});
2312
+ sendResponse(response);
2313
+ });
2314
+ }
2315
+ /* istanbul ignore next */
2316
+ _on_Cancel(message, channel) {
2317
+ return g_sendError(channel, message, node_opcua_types_1.CancelResponse, node_opcua_status_code_1.StatusCodes.BadServiceUnsupported);
2318
+ }
2319
+ // NodeManagement Service Set Overview
2320
+ // This Service Set defines Services to add and delete AddressSpace Nodes and References between them. All added
2321
+ // Nodes continue to exist in the AddressSpace even if the Client that created them disconnects from the Server.
2322
+ //
2323
+ /* istanbul ignore next */
2324
+ _on_AddNodes(message, channel) {
2325
+ return g_sendError(channel, message, node_opcua_service_node_management_1.AddNodesResponse, node_opcua_status_code_1.StatusCodes.BadServiceUnsupported);
2326
+ }
2327
+ /* istanbul ignore next */
2328
+ _on_AddReferences(message, channel) {
2329
+ return g_sendError(channel, message, node_opcua_service_node_management_1.AddReferencesResponse, node_opcua_status_code_1.StatusCodes.BadServiceUnsupported);
2330
+ }
2331
+ /* istanbul ignore next */
2332
+ _on_DeleteNodes(message, channel) {
2333
+ return g_sendError(channel, message, node_opcua_service_node_management_1.DeleteNodesResponse, node_opcua_status_code_1.StatusCodes.BadServiceUnsupported);
2334
+ }
2335
+ /* istanbul ignore next */
2336
+ _on_DeleteReferences(message, channel) {
2337
+ return g_sendError(channel, message, node_opcua_service_node_management_1.DeleteReferencesResponse, node_opcua_status_code_1.StatusCodes.BadServiceUnsupported);
2338
+ }
2339
+ // Query Service
2340
+ /* istanbul ignore next */
2341
+ _on_QueryFirst(message, channel) {
2342
+ return g_sendError(channel, message, node_opcua_service_query_1.QueryFirstResponse, node_opcua_status_code_1.StatusCodes.BadServiceUnsupported);
2343
+ }
2344
+ /* istanbul ignore next */
2345
+ _on_QueryNext(message, channel) {
2346
+ return g_sendError(channel, message, node_opcua_service_query_1.QueryNextResponse, node_opcua_status_code_1.StatusCodes.BadServiceUnsupported);
2347
+ }
2348
+ /* istanbul ignore next */
2349
+ _on_HistoryUpdate(message, channel) {
2350
+ return g_sendError(channel, message, node_opcua_service_history_1.HistoryUpdateResponse, node_opcua_status_code_1.StatusCodes.BadServiceUnsupported);
2351
+ }
2352
+ createEndpoint(port1, serverOptions) {
2353
+ // add the tcp/ip endpoint with no security
2354
+ const endPoint = new server_end_point_1.OPCUAServerEndPoint({
2355
+ port: port1,
2356
+ certificateManager: this.serverCertificateManager,
2357
+ certificateChain: this.getCertificateChain(),
2358
+ privateKey: this.getPrivateKey(),
2359
+ defaultSecureTokenLifetime: serverOptions.defaultSecureTokenLifetime || 600000,
2360
+ timeout: serverOptions.timeout || 3 * 60 * 1000,
2361
+ maxConnections: this.maxConnectionsPerEndpoint,
2362
+ objectFactory: this.objectFactory,
2363
+ serverInfo: this.serverInfo
2364
+ });
2365
+ return endPoint;
2366
+ }
2367
+ createEndpointDescriptions(serverOption, endpointOptions) {
2368
+ /* istanbul ignore next */
2369
+ if (!endpointOptions) {
2370
+ throw new Error("internal error");
2371
+ }
2372
+ const hostname = (0, node_opcua_hostname_1.getFullyQualifiedDomainName)();
2373
+ endpointOptions.hostname = endpointOptions.hostname || hostname;
2374
+ endpointOptions.port = endpointOptions.port || 26543;
2375
+ /* istanbul ignore next */
2376
+ if (!Object.prototype.hasOwnProperty.call(endpointOptions, "port") ||
2377
+ !isFinite(endpointOptions.port) ||
2378
+ typeof endpointOptions.port !== "number") {
2379
+ throw new Error("expecting a valid port (number)");
2380
+ }
2381
+ const port = Number(endpointOptions.port || 0);
2382
+ const endPoint = this.createEndpoint(port, serverOption);
2383
+ endpointOptions.alternateHostname = endpointOptions.alternateHostname || [];
2384
+ const alternateHostname = endpointOptions.alternateHostname instanceof Array
2385
+ ? endpointOptions.alternateHostname
2386
+ : [endpointOptions.alternateHostname];
2387
+ const allowAnonymous = endpointOptions.allowAnonymous === undefined ? true : !!endpointOptions.allowAnonymous;
2388
+ endPoint.addStandardEndpointDescriptions({
2389
+ allowAnonymous,
2390
+ securityModes: endpointOptions.securityModes,
2391
+ securityPolicies: endpointOptions.securityPolicies,
2392
+ hostname: endpointOptions.hostname,
2393
+ alternateHostname,
2394
+ disableDiscovery: !!endpointOptions.disableDiscovery,
2395
+ // xx hostname,
2396
+ resourcePath: serverOption.resourcePath || ""
2397
+ });
2398
+ return endPoint;
2399
+ }
2400
+ initializeCM() {
2401
+ const _super = Object.create(null, {
2402
+ initializeCM: { get: () => super.initializeCM }
2403
+ });
2404
+ return __awaiter(this, void 0, void 0, function* () {
2405
+ yield _super.initializeCM.call(this);
2406
+ yield this.userCertificateManager.initialize();
2407
+ });
2408
+ }
2409
+ }
2410
+ exports.OPCUAServer = OPCUAServer;
2411
+ OPCUAServer.defaultShutdownTimeout = 100; // 250 ms
2412
+ /**
2413
+ * if requestExactEndpointUrl is set to true the server will only accept createSession that have a endpointUrl that strictly matches
2414
+ * one of the provided endpoint.
2415
+ * This mean that if the server expose a endpoint with url such as opc.tcp://MYHOSTNAME:1234, client will not be able to reach the server
2416
+ * with the ip address of the server.
2417
+ * requestExactEndpointUrl = true => emulates the Prosys Server behavior
2418
+ * requestExactEndpointUrl = false => emulates the Unified Automation behavior.
2419
+ */
2420
+ OPCUAServer.requestExactEndpointUrl = g_requestExactEndpointUrl;
2421
+ OPCUAServer.registry = new node_opcua_object_registry_1.ObjectRegistry();
2422
+ OPCUAServer.fallbackSessionName = "Client didn't provide a meaningful sessionName ...";
2423
+ /**
2424
+ * the maximum number of subscription that can be created per server
2425
+ * @deprecated
2426
+ */
2427
+ OPCUAServer.deprectated_MAX_SUBSCRIPTION = 50;
2428
+ const opts = { multiArgs: false };
2429
+ OPCUAServer.prototype.start = thenify.withCallback(OPCUAServer.prototype.start, opts);
2430
+ OPCUAServer.prototype.initialize = thenify.withCallback(OPCUAServer.prototype.initialize, opts);
2431
+ OPCUAServer.prototype.shutdown = thenify.withCallback(OPCUAServer.prototype.shutdown, opts);
2432
2432
  //# sourceMappingURL=opcua_server.js.map