node-opcua-server 2.163.1 → 2.165.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/addressSpace_accessor.js +7 -5
- package/dist/addressSpace_accessor.js.map +1 -1
- package/dist/base_server.d.ts +95 -18
- package/dist/base_server.js +217 -69
- package/dist/base_server.js.map +1 -1
- package/dist/monitored_item.js +32 -32
- package/dist/monitored_item.js.map +1 -1
- package/dist/node_sampler.js +1 -1
- package/dist/node_sampler.js.map +1 -1
- package/dist/opcua_server.d.ts +171 -123
- package/dist/opcua_server.js +466 -223
- package/dist/opcua_server.js.map +1 -1
- package/dist/register_server_manager.d.ts +2 -2
- package/dist/register_server_manager.js +12 -6
- package/dist/register_server_manager.js.map +1 -1
- package/dist/register_server_manager_mdns_only.js +1 -1
- package/dist/register_server_manager_mdns_only.js.map +1 -1
- package/dist/server_end_point.d.ts +108 -12
- package/dist/server_end_point.js +157 -57
- package/dist/server_end_point.js.map +1 -1
- package/dist/server_engine.d.ts +32 -14
- package/dist/server_engine.js +160 -59
- package/dist/server_engine.js.map +1 -1
- package/dist/server_publish_engine.js +5 -5
- package/dist/server_publish_engine.js.map +1 -1
- package/dist/server_session.js +4 -4
- package/dist/server_session.js.map +1 -1
- package/dist/server_subscription.js +18 -18
- package/dist/server_subscription.js.map +1 -1
- package/dist/sessions_compatible_for_transfer.js +1 -1
- package/dist/sessions_compatible_for_transfer.js.map +1 -1
- package/package.json +47 -47
- package/source/addressSpace_accessor.ts +6 -3
- package/source/base_server.ts +252 -90
- package/source/monitored_item.ts +32 -32
- package/source/node_sampler.ts +1 -1
- package/source/opcua_server.ts +674 -489
- package/source/register_server_manager.ts +11 -5
- package/source/register_server_manager_mdns_only.ts +1 -1
- package/source/server_end_point.ts +278 -94
- package/source/server_engine.ts +246 -135
- package/source/server_publish_engine.ts +5 -5
- package/source/server_session.ts +4 -4
- package/source/server_subscription.ts +18 -18
- package/source/sessions_compatible_for_transfer.ts +4 -2
package/dist/opcua_server.js
CHANGED
|
@@ -9,20 +9,18 @@ exports.filterDiagnosticInfo = filterDiagnosticInfo;
|
|
|
9
9
|
/**
|
|
10
10
|
* @module node-opcua-server
|
|
11
11
|
*/
|
|
12
|
-
const
|
|
13
|
-
const
|
|
14
|
-
const async_1 = __importDefault(require("async"));
|
|
12
|
+
const node_crypto_1 = require("node:crypto");
|
|
13
|
+
const node_util_1 = require("node:util");
|
|
15
14
|
const chalk_1 = __importDefault(require("chalk"));
|
|
16
|
-
const node_opcua_hostname_1 = require("node-opcua-hostname");
|
|
17
|
-
const node_opcua_assert_1 = require("node-opcua-assert");
|
|
18
|
-
const node_opcua_utils_1 = require("node-opcua-utils");
|
|
19
15
|
const node_opcua_address_space_1 = require("node-opcua-address-space");
|
|
16
|
+
const node_opcua_assert_1 = require("node-opcua-assert");
|
|
20
17
|
const node_opcua_certificate_manager_1 = require("node-opcua-certificate-manager");
|
|
21
18
|
const node_opcua_common_1 = require("node-opcua-common");
|
|
22
19
|
const web_1 = require("node-opcua-crypto/web");
|
|
23
20
|
const node_opcua_data_model_1 = require("node-opcua-data-model");
|
|
24
21
|
const node_opcua_data_value_1 = require("node-opcua-data-value");
|
|
25
22
|
const node_opcua_debug_1 = require("node-opcua-debug");
|
|
23
|
+
const node_opcua_hostname_1 = require("node-opcua-hostname");
|
|
26
24
|
const node_opcua_object_registry_1 = require("node-opcua-object-registry");
|
|
27
25
|
const node_opcua_secure_channel_1 = require("node-opcua-secure-channel");
|
|
28
26
|
const node_opcua_service_browse_1 = require("node-opcua-service-browse");
|
|
@@ -39,9 +37,9 @@ const node_opcua_service_translate_browse_path_1 = require("node-opcua-service-t
|
|
|
39
37
|
const node_opcua_service_write_1 = require("node-opcua-service-write");
|
|
40
38
|
const node_opcua_status_code_1 = require("node-opcua-status-code");
|
|
41
39
|
const node_opcua_types_1 = require("node-opcua-types");
|
|
40
|
+
const node_opcua_utils_1 = require("node-opcua-utils");
|
|
42
41
|
const node_opcua_variant_1 = require("node-opcua-variant");
|
|
43
|
-
const
|
|
44
|
-
const node_opcua_utils_2 = require("node-opcua-utils");
|
|
42
|
+
const thenify_ex_1 = require("thenify-ex");
|
|
45
43
|
const base_server_1 = require("./base_server");
|
|
46
44
|
const factory_1 = require("./factory");
|
|
47
45
|
const monitored_item_1 = require("./monitored_item");
|
|
@@ -55,19 +53,16 @@ const user_manager_ua_1 = require("./user_manager_ua");
|
|
|
55
53
|
function isSubscriptionIdInvalid(subscriptionId) {
|
|
56
54
|
return subscriptionId < 0 || subscriptionId >= 0xffffffff;
|
|
57
55
|
}
|
|
58
|
-
// tslint:disable-next-line:no-var-requires
|
|
59
|
-
const thenify_ex_1 = require("thenify-ex");
|
|
60
|
-
// tslint:disable-next-line:no-var-requires
|
|
61
56
|
const package_info = require("../package.json");
|
|
62
57
|
const debugLog = (0, node_opcua_debug_1.make_debugLog)(__filename);
|
|
63
58
|
const errorLog = (0, node_opcua_debug_1.make_errorLog)(__filename);
|
|
64
59
|
const warningLog = (0, node_opcua_debug_1.make_warningLog)(__filename);
|
|
65
60
|
const default_maxConnectionsPerEndpoint = 10;
|
|
66
|
-
function g_sendError(channel, message,
|
|
61
|
+
function g_sendError(channel, message, _ResponseClass, statusCode) {
|
|
67
62
|
const response = new node_opcua_types_1.ServiceFault({
|
|
68
63
|
responseHeader: { serviceResult: statusCode }
|
|
69
64
|
});
|
|
70
|
-
|
|
65
|
+
channel.send_response("MSG", response, message);
|
|
71
66
|
}
|
|
72
67
|
const default_build_info = {
|
|
73
68
|
manufacturerName: "NodeOPCUA : MIT Licence ( see http://node-opcua.github.io/)",
|
|
@@ -90,7 +85,7 @@ function _adjust_session_timeout(sessionTimeout) {
|
|
|
90
85
|
}
|
|
91
86
|
function channel_has_session(channel, session) {
|
|
92
87
|
if (session.channel === channel) {
|
|
93
|
-
(0, node_opcua_assert_1.assert)(Object.
|
|
88
|
+
(0, node_opcua_assert_1.assert)(Object.hasOwn(channel.sessionTokens, session.authenticationToken.toString()));
|
|
94
89
|
return true;
|
|
95
90
|
}
|
|
96
91
|
return false;
|
|
@@ -102,12 +97,12 @@ function moveSessionToChannel(session, channel) {
|
|
|
102
97
|
}
|
|
103
98
|
session._detach_channel();
|
|
104
99
|
session._attach_channel(channel);
|
|
105
|
-
(0, node_opcua_assert_1.assert)(session.channel
|
|
100
|
+
(0, node_opcua_assert_1.assert)(session.channel?.channelId === channel.channelId);
|
|
106
101
|
}
|
|
107
102
|
async function _attempt_to_close_some_old_unactivated_session(server) {
|
|
108
|
-
const session = server.engine
|
|
103
|
+
const session = server.engine?.getOldestInactiveSession();
|
|
109
104
|
if (session) {
|
|
110
|
-
await server.engine
|
|
105
|
+
await server.engine?.closeSession(session.authenticationToken, false, "Forcing");
|
|
111
106
|
}
|
|
112
107
|
}
|
|
113
108
|
function getRequiredEndpointInfo(endpoint) {
|
|
@@ -129,7 +124,7 @@ function getRequiredEndpointInfo(endpoint) {
|
|
|
129
124
|
userIdentityTokens: endpoint.userIdentityTokens
|
|
130
125
|
});
|
|
131
126
|
// reduce even further by explicitly setting unwanted members to null
|
|
132
|
-
e.server.applicationName =
|
|
127
|
+
e.server.applicationName = new node_opcua_data_model_1.LocalizedText({ text: "" });
|
|
133
128
|
// xx e.server.applicationType = null as any;
|
|
134
129
|
e.server.gatewayServerUri = null;
|
|
135
130
|
e.server.discoveryProfileUri = null;
|
|
@@ -145,9 +140,9 @@ function _serverEndpointsForCreateSessionResponse(server, endpointUrl, serverUri
|
|
|
145
140
|
// https://reference.opcfoundation.org/v104/Core/docs/Part4/5.6.2/
|
|
146
141
|
// https://reference.opcfoundation.org/v105/Core/docs/Part4/5.6.2/
|
|
147
142
|
return server
|
|
148
|
-
.
|
|
143
|
+
.findMatchingEndpoints(endpointUrl)
|
|
149
144
|
.filter((e) => !e.restricted) // remove restricted endpoints
|
|
150
|
-
.filter((e) => (0,
|
|
145
|
+
.filter((e) => (0, node_opcua_utils_1.matchUri)(e.endpointUrl, endpointUrl))
|
|
151
146
|
.map(getRequiredEndpointInfo);
|
|
152
147
|
}
|
|
153
148
|
function adjustSecurityPolicy(channel, userTokenPolicy_securityPolicyUri) {
|
|
@@ -162,11 +157,17 @@ function adjustSecurityPolicy(channel, userTokenPolicy_securityPolicyUri) {
|
|
|
162
157
|
}
|
|
163
158
|
function findUserTokenByPolicy(endpoint_description, userTokenType, policyId) {
|
|
164
159
|
(0, node_opcua_assert_1.assert)(endpoint_description instanceof node_opcua_types_1.EndpointDescription);
|
|
160
|
+
if (!endpoint_description.userIdentityTokens) {
|
|
161
|
+
return null;
|
|
162
|
+
}
|
|
165
163
|
const r = endpoint_description.userIdentityTokens.filter((userIdentity) => userIdentity.tokenType === userTokenType && (!policyId || userIdentity.policyId === policyId));
|
|
166
164
|
return r.length === 0 ? null : r[0];
|
|
167
165
|
}
|
|
168
166
|
function findUserTokenPolicy(endpoint_description, userTokenType) {
|
|
169
167
|
(0, node_opcua_assert_1.assert)(endpoint_description instanceof node_opcua_types_1.EndpointDescription);
|
|
168
|
+
if (!endpoint_description.userIdentityTokens) {
|
|
169
|
+
return null;
|
|
170
|
+
}
|
|
170
171
|
const r = endpoint_description.userIdentityTokens.filter((userIdentity) => {
|
|
171
172
|
(0, node_opcua_assert_1.assert)(userIdentity.tokenType !== undefined);
|
|
172
173
|
return userIdentity.tokenType === userTokenType;
|
|
@@ -182,6 +183,12 @@ function createAnonymousIdentityToken(endpoint_desc) {
|
|
|
182
183
|
return new node_opcua_service_session_1.AnonymousIdentityToken({ policyId: userTokenPolicy.policyId });
|
|
183
184
|
}
|
|
184
185
|
function sameIdentityToken(token1, token2) {
|
|
186
|
+
if (!token1 && !token2) {
|
|
187
|
+
return true;
|
|
188
|
+
}
|
|
189
|
+
if (!token1 || !token2) {
|
|
190
|
+
return false;
|
|
191
|
+
}
|
|
185
192
|
if (token1 instanceof node_opcua_service_session_1.UserNameIdentityToken) {
|
|
186
193
|
if (!(token2 instanceof node_opcua_service_session_1.UserNameIdentityToken)) {
|
|
187
194
|
return false;
|
|
@@ -262,7 +269,7 @@ function monitoredItem_read_and_record_value_async(self, context, oldValue, node
|
|
|
262
269
|
function build_scanning_node_function(addressSpace, itemToMonitor) {
|
|
263
270
|
(0, node_opcua_assert_1.assert)(itemToMonitor instanceof node_opcua_service_read_1.ReadValueId);
|
|
264
271
|
const node = addressSpace.findNode(itemToMonitor.nodeId);
|
|
265
|
-
/*
|
|
272
|
+
/* c8 ignore next */
|
|
266
273
|
if (!node) {
|
|
267
274
|
errorLog(" INVALID NODE ID , ", itemToMonitor.nodeId.toString());
|
|
268
275
|
(0, node_opcua_debug_1.dump)(itemToMonitor);
|
|
@@ -299,7 +306,7 @@ function build_scanning_node_function(addressSpace, itemToMonitor) {
|
|
|
299
306
|
};
|
|
300
307
|
}
|
|
301
308
|
}
|
|
302
|
-
function prepareMonitoredItem(
|
|
309
|
+
function prepareMonitoredItem(_context, addressSpace, monitoredItem) {
|
|
303
310
|
const itemToMonitor = monitoredItem.itemToMonitor;
|
|
304
311
|
const readNodeFunc = build_scanning_node_function(addressSpace, itemToMonitor);
|
|
305
312
|
monitoredItem.samplingFunc = readNodeFunc;
|
|
@@ -311,7 +318,7 @@ function isMonitoringModeValid(monitoringMode) {
|
|
|
311
318
|
function _installRegisterServerManager(self) {
|
|
312
319
|
(0, node_opcua_assert_1.assert)(self instanceof OPCUAServer);
|
|
313
320
|
(0, node_opcua_assert_1.assert)(!self.registerServerManager);
|
|
314
|
-
/*
|
|
321
|
+
/* c8 ignore next */
|
|
315
322
|
if (!self.registerServerMethod) {
|
|
316
323
|
throw new Error("Internal Error");
|
|
317
324
|
}
|
|
@@ -332,7 +339,7 @@ function _installRegisterServerManager(self) {
|
|
|
332
339
|
server: self
|
|
333
340
|
});
|
|
334
341
|
break;
|
|
335
|
-
/*
|
|
342
|
+
/* c8 ignore next */
|
|
336
343
|
default:
|
|
337
344
|
throw new Error("Invalid switch");
|
|
338
345
|
}
|
|
@@ -374,7 +381,7 @@ function _installRegisterServerManager(self) {
|
|
|
374
381
|
});
|
|
375
382
|
}
|
|
376
383
|
function validate_applicationUri(channel, request) {
|
|
377
|
-
const applicationUri = request.clientDescription.applicationUri;
|
|
384
|
+
const applicationUri = request.clientDescription.applicationUri || "";
|
|
378
385
|
const clientCertificate = request.clientCertificate;
|
|
379
386
|
// if session is insecure there is no need to check certificate information
|
|
380
387
|
if (channel.securityMode === node_opcua_secure_channel_1.MessageSecurityMode.None) {
|
|
@@ -384,9 +391,9 @@ function validate_applicationUri(channel, request) {
|
|
|
384
391
|
return true; // can't check
|
|
385
392
|
}
|
|
386
393
|
const e = (0, web_1.exploreCertificate)(clientCertificate);
|
|
387
|
-
const uniformResourceIdentifier = e.tbsCertificate.extensions
|
|
394
|
+
const uniformResourceIdentifier = e.tbsCertificate.extensions?.subjectAltName?.uniformResourceIdentifier ?? null;
|
|
388
395
|
const applicationUriFromCert = uniformResourceIdentifier && uniformResourceIdentifier.length > 0 ? uniformResourceIdentifier[0] : null;
|
|
389
|
-
/*
|
|
396
|
+
/* c8 ignore next */
|
|
390
397
|
if (applicationUriFromCert !== applicationUri) {
|
|
391
398
|
errorLog("BadCertificateUriInvalid!");
|
|
392
399
|
errorLog("applicationUri = ", applicationUri);
|
|
@@ -396,7 +403,7 @@ function validate_applicationUri(channel, request) {
|
|
|
396
403
|
}
|
|
397
404
|
function validate_security_endpoint(server, request, channel) {
|
|
398
405
|
debugLog("validate_security_endpoint = ", request.endpointUrl);
|
|
399
|
-
let endpoints = server.
|
|
406
|
+
let endpoints = server.findMatchingEndpoints(request.endpointUrl);
|
|
400
407
|
// endpointUrl String The network address that the Client used to access the Session Endpoint.
|
|
401
408
|
// The HostName portion of the URL should be one of the HostNames for the application that are
|
|
402
409
|
// specified in the Server’s ApplicationInstanceCertificate (see 7.2). The Server shall raise an
|
|
@@ -408,22 +415,22 @@ function validate_security_endpoint(server, request, channel) {
|
|
|
408
415
|
// sometime endpoints have a extra leading "/" that can be ignored
|
|
409
416
|
// don't be too harsh.
|
|
410
417
|
if (endpoints.length === 0 && request.endpointUrl?.endsWith("/")) {
|
|
411
|
-
endpoints = server.
|
|
418
|
+
endpoints = server.findMatchingEndpoints(request.endpointUrl.slice(0, -1));
|
|
412
419
|
}
|
|
413
420
|
if (endpoints.length === 0) {
|
|
414
421
|
// we have a UrlMismatch here
|
|
415
|
-
const ua_server = server.engine.addressSpace
|
|
422
|
+
const ua_server = server.engine.addressSpace?.rootFolder.objects.server;
|
|
416
423
|
if (!request.endpointUrl?.match(/localhost/i) || OPCUAServer.requestExactEndpointUrl) {
|
|
417
424
|
warningLog("Cannot find suitable endpoints in available endpoints. endpointUri =", request.endpointUrl);
|
|
418
425
|
}
|
|
419
|
-
ua_server
|
|
426
|
+
ua_server?.raiseEvent("AuditUrlMismatchEventType", {
|
|
420
427
|
endpointUrl: { dataType: node_opcua_variant_1.DataType.String, value: request.endpointUrl }
|
|
421
428
|
});
|
|
422
429
|
if (OPCUAServer.requestExactEndpointUrl) {
|
|
423
430
|
return { errCode: node_opcua_status_code_1.StatusCodes.BadServiceUnsupported };
|
|
424
431
|
}
|
|
425
432
|
else {
|
|
426
|
-
endpoints = server.
|
|
433
|
+
endpoints = server.findMatchingEndpoints(null);
|
|
427
434
|
}
|
|
428
435
|
}
|
|
429
436
|
// ignore restricted endpoints
|
|
@@ -435,7 +442,7 @@ function validate_security_endpoint(server, request, channel) {
|
|
|
435
442
|
return { errCode: node_opcua_status_code_1.StatusCodes.BadSecurityModeRejected };
|
|
436
443
|
}
|
|
437
444
|
const endpoints_matching_security_policy = endpoints_matching_security_mode.filter((e) => {
|
|
438
|
-
return e.securityPolicyUri === channel
|
|
445
|
+
return e.securityPolicyUri === channel?.securityPolicy;
|
|
439
446
|
});
|
|
440
447
|
if (endpoints_matching_security_policy.length === 0) {
|
|
441
448
|
return { errCode: node_opcua_status_code_1.StatusCodes.BadSecurityPolicyRejected };
|
|
@@ -443,7 +450,10 @@ function validate_security_endpoint(server, request, channel) {
|
|
|
443
450
|
if (endpoints_matching_security_policy.length !== 1) {
|
|
444
451
|
debugLog("endpoints_matching_security_policy= ", endpoints_matching_security_policy.length);
|
|
445
452
|
}
|
|
446
|
-
return {
|
|
453
|
+
return {
|
|
454
|
+
errCode: node_opcua_status_code_1.StatusCodes.Good,
|
|
455
|
+
endpoint: endpoints_matching_security_policy[0]
|
|
456
|
+
};
|
|
447
457
|
}
|
|
448
458
|
function filterDiagnosticInfo(returnDiagnostics, response) {
|
|
449
459
|
if (node_opcua_data_model_1.RESPONSE_DIAGNOSTICS_MASK_ALL & returnDiagnostics) {
|
|
@@ -477,6 +487,12 @@ const g_requestExactEndpointUrl = !!process.env.NODEOPCUA_SERVER_REQUEST_EXACT_E
|
|
|
477
487
|
*
|
|
478
488
|
*/
|
|
479
489
|
class OPCUAServer extends base_server_1.OPCUABaseServer {
|
|
490
|
+
engine;
|
|
491
|
+
registerServerMethod;
|
|
492
|
+
discoveryServerEndpointUrl;
|
|
493
|
+
registerServerManager;
|
|
494
|
+
capabilitiesForMDNS;
|
|
495
|
+
userCertificateManager;
|
|
480
496
|
static defaultShutdownTimeout = 100; // 250 ms
|
|
481
497
|
/**
|
|
482
498
|
* if requestExactEndpointUrl is set to true the server will only accept createSession that have a endpointUrl that strictly matches
|
|
@@ -575,6 +591,117 @@ class OPCUAServer extends base_server_1.OPCUABaseServer {
|
|
|
575
591
|
get isAuditing() {
|
|
576
592
|
return this.engine ? this.engine.isAuditing : false;
|
|
577
593
|
}
|
|
594
|
+
/**
|
|
595
|
+
* Set the current server state.
|
|
596
|
+
*
|
|
597
|
+
* Updates both the internal state and the
|
|
598
|
+
* `Server.ServerStatus.State` variable in the
|
|
599
|
+
* address space so that OPC UA reads reflect the
|
|
600
|
+
* new state immediately.
|
|
601
|
+
*/
|
|
602
|
+
setServerState(serverState) {
|
|
603
|
+
this.engine.setServerState(serverState);
|
|
604
|
+
}
|
|
605
|
+
/**
|
|
606
|
+
* Read the current `ServerState` from the
|
|
607
|
+
* internal server status.
|
|
608
|
+
*/
|
|
609
|
+
getServerState() {
|
|
610
|
+
return this.engine.getServerState();
|
|
611
|
+
}
|
|
612
|
+
/**
|
|
613
|
+
* Set or clear a temporary role-policy override.
|
|
614
|
+
*
|
|
615
|
+
* When set, the override's `getUserRoles(username)`
|
|
616
|
+
* is called **before** the default `userManager`.
|
|
617
|
+
* Returning a `NodeId[]` overrides the roles;
|
|
618
|
+
* returning `null` falls through to the default.
|
|
619
|
+
*
|
|
620
|
+
* Call with `null` to remove the override and
|
|
621
|
+
* restore default behavior.
|
|
622
|
+
*/
|
|
623
|
+
setRolePolicyOverride(override) {
|
|
624
|
+
this.rolePolicyOverride = override;
|
|
625
|
+
}
|
|
626
|
+
/**
|
|
627
|
+
* Set `ServerConfiguration.InApplicationSetup` in
|
|
628
|
+
* the address space.
|
|
629
|
+
*
|
|
630
|
+
* Indicates whether the server is in its initial
|
|
631
|
+
* application setup phase (e.g. awaiting GDS
|
|
632
|
+
* provisioning).
|
|
633
|
+
*/
|
|
634
|
+
setInApplicationSetup(value) {
|
|
635
|
+
this.engine.setInApplicationSetup(value);
|
|
636
|
+
}
|
|
637
|
+
/**
|
|
638
|
+
* Read the current value of
|
|
639
|
+
* `ServerConfiguration.InApplicationSetup`.
|
|
640
|
+
*/
|
|
641
|
+
getInApplicationSetup() {
|
|
642
|
+
return this.engine.getInApplicationSetup();
|
|
643
|
+
}
|
|
644
|
+
/**
|
|
645
|
+
* Collect additional hostnames for the self-signed certificate SAN.
|
|
646
|
+
*
|
|
647
|
+
* Merges hostnames from `alternateHostname` and parsed
|
|
648
|
+
* `advertisedEndpoints` URLs so the certificate covers all
|
|
649
|
+
* configured addresses.
|
|
650
|
+
*
|
|
651
|
+
* IP literals (v4/v6) are **excluded** — they are handled by
|
|
652
|
+
* `getConfiguredIPs()` and placed in the SAN `iPAddress` entries.
|
|
653
|
+
*
|
|
654
|
+
* @internal
|
|
655
|
+
*/
|
|
656
|
+
getConfiguredHostnames() {
|
|
657
|
+
return this._collectAlternateValues().hostnames;
|
|
658
|
+
}
|
|
659
|
+
/**
|
|
660
|
+
* Collect additional IP addresses for the self-signed certificate SAN.
|
|
661
|
+
*
|
|
662
|
+
* Merges IP literals from `alternateHostname` and parsed
|
|
663
|
+
* `advertisedEndpoints` URLs so the certificate covers all
|
|
664
|
+
* configured IP addresses.
|
|
665
|
+
*
|
|
666
|
+
* @internal
|
|
667
|
+
*/
|
|
668
|
+
getConfiguredIPs() {
|
|
669
|
+
return this._collectAlternateValues().ips;
|
|
670
|
+
}
|
|
671
|
+
/**
|
|
672
|
+
* Classify all values from `alternateHostname` and
|
|
673
|
+
* `advertisedEndpoints` into hostnames vs IP addresses using
|
|
674
|
+
* `isIPAddress()` (wraps `net.isIP()`).
|
|
675
|
+
*/
|
|
676
|
+
_collectAlternateValues() {
|
|
677
|
+
const hostnames = [];
|
|
678
|
+
const ips = [];
|
|
679
|
+
// alternateHostname
|
|
680
|
+
const alt = this.options.alternateHostname;
|
|
681
|
+
if (alt) {
|
|
682
|
+
const altArray = Array.isArray(alt) ? alt : [alt];
|
|
683
|
+
for (const value of altArray) {
|
|
684
|
+
if ((0, node_opcua_hostname_1.isIPAddress)(value)) {
|
|
685
|
+
ips.push(value);
|
|
686
|
+
}
|
|
687
|
+
else {
|
|
688
|
+
hostnames.push(value);
|
|
689
|
+
}
|
|
690
|
+
}
|
|
691
|
+
}
|
|
692
|
+
// advertisedEndpoints — normalize to AdvertisedEndpointConfig[]
|
|
693
|
+
const advList = (0, server_end_point_1.normalizeAdvertisedEndpoints)(this.options.advertisedEndpoints);
|
|
694
|
+
for (const config of advList) {
|
|
695
|
+
const { hostname } = (0, server_end_point_1.parseOpcTcpUrl)(config.url);
|
|
696
|
+
if ((0, node_opcua_hostname_1.isIPAddress)(hostname)) {
|
|
697
|
+
ips.push(hostname);
|
|
698
|
+
}
|
|
699
|
+
else {
|
|
700
|
+
hostnames.push(hostname);
|
|
701
|
+
}
|
|
702
|
+
}
|
|
703
|
+
return { hostnames, ips };
|
|
704
|
+
}
|
|
578
705
|
static registry = new node_opcua_object_registry_1.ObjectRegistry();
|
|
579
706
|
static fallbackSessionName = "Client didn't provide a meaningful sessionName ...";
|
|
580
707
|
/**
|
|
@@ -651,14 +778,14 @@ class OPCUAServer extends base_server_1.OPCUABaseServer {
|
|
|
651
778
|
// note: we need to delay initialization of endpoint as certain resources
|
|
652
779
|
// such as %FQDN% might not be ready yet at this stage
|
|
653
780
|
this._delayInit = async () => {
|
|
654
|
-
/*
|
|
781
|
+
/* c8 ignore next */
|
|
655
782
|
if (!options) {
|
|
656
783
|
throw new Error("Internal Error");
|
|
657
784
|
}
|
|
658
785
|
// to check => this.serverInfo.applicationName = this.serverInfo.productName || buildInfo.productName;
|
|
659
786
|
// note: applicationUri is handled in a special way
|
|
660
787
|
this.engine = new server_engine_1.ServerEngine({
|
|
661
|
-
applicationUri: () => this.serverInfo.applicationUri,
|
|
788
|
+
applicationUri: () => this.serverInfo.applicationUri || "",
|
|
662
789
|
buildInfo,
|
|
663
790
|
isAuditing: options.isAuditing,
|
|
664
791
|
serverCapabilities: options.serverCapabilities,
|
|
@@ -691,6 +818,7 @@ class OPCUAServer extends base_server_1.OPCUABaseServer {
|
|
|
691
818
|
host: options.host,
|
|
692
819
|
allowAnonymous: options.allowAnonymous,
|
|
693
820
|
alternateHostname: options.alternateHostname,
|
|
821
|
+
advertisedEndpoints: options.advertisedEndpoints,
|
|
694
822
|
disableDiscovery: options.disableDiscovery,
|
|
695
823
|
securityModes: options.securityModes,
|
|
696
824
|
securityPolicies: options.securityPolicies
|
|
@@ -718,7 +846,7 @@ class OPCUAServer extends base_server_1.OPCUABaseServer {
|
|
|
718
846
|
const done = args[0];
|
|
719
847
|
(0, node_opcua_assert_1.assert)(!this.initialized, "server is already initialized"); // already initialized ?
|
|
720
848
|
this._preInitTask.push(async () => {
|
|
721
|
-
/*
|
|
849
|
+
/* c8 ignore next */
|
|
722
850
|
if (this._delayInit) {
|
|
723
851
|
await this._delayInit();
|
|
724
852
|
this._delayInit = undefined;
|
|
@@ -728,6 +856,10 @@ class OPCUAServer extends base_server_1.OPCUABaseServer {
|
|
|
728
856
|
.then(() => {
|
|
729
857
|
OPCUAServer.registry.register(this);
|
|
730
858
|
this.engine.initialize(this.options, () => {
|
|
859
|
+
if (!this.engine.addressSpace) {
|
|
860
|
+
done(new Error("no addressSpace"));
|
|
861
|
+
return;
|
|
862
|
+
}
|
|
731
863
|
(0, user_manager_ua_1.bindRoleSet)(this.userManager, this.engine.addressSpace);
|
|
732
864
|
setImmediate(() => {
|
|
733
865
|
this.emit("post_initialize");
|
|
@@ -740,41 +872,40 @@ class OPCUAServer extends base_server_1.OPCUABaseServer {
|
|
|
740
872
|
});
|
|
741
873
|
}
|
|
742
874
|
start(...args) {
|
|
743
|
-
const
|
|
744
|
-
|
|
745
|
-
|
|
875
|
+
const callback = args[0];
|
|
876
|
+
if (callback) {
|
|
877
|
+
return super.start(callback);
|
|
878
|
+
}
|
|
879
|
+
return super.start();
|
|
880
|
+
}
|
|
881
|
+
/**
|
|
882
|
+
* Initiate the server by starting all its endpoints
|
|
883
|
+
* @private
|
|
884
|
+
*/
|
|
885
|
+
async startAsync() {
|
|
886
|
+
await (0, node_opcua_hostname_1.extractFullyQualifiedDomainName)();
|
|
746
887
|
if (!this.initialized) {
|
|
747
|
-
|
|
748
|
-
this.initialize(callback);
|
|
749
|
-
});
|
|
888
|
+
await this.initialize();
|
|
750
889
|
}
|
|
751
|
-
|
|
752
|
-
super.
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
/* empty */
|
|
763
|
-
}).catch((err) => {
|
|
764
|
-
/* empty */
|
|
765
|
-
});
|
|
766
|
-
setImmediate(callback);
|
|
767
|
-
}
|
|
768
|
-
});
|
|
890
|
+
try {
|
|
891
|
+
await super.startAsync();
|
|
892
|
+
}
|
|
893
|
+
catch (err) {
|
|
894
|
+
await this.shutdown();
|
|
895
|
+
throw err;
|
|
896
|
+
}
|
|
897
|
+
// we start the registration process asynchronously
|
|
898
|
+
// as we want to make server immediately available
|
|
899
|
+
this.registerServerManager?.start().catch(() => {
|
|
900
|
+
/* empty */
|
|
769
901
|
});
|
|
770
|
-
async_1.default.series(tasks, done);
|
|
771
902
|
}
|
|
772
903
|
shutdown(...args) {
|
|
773
904
|
const timeout = args.length === 1 ? OPCUAServer.defaultShutdownTimeout : args[0];
|
|
774
905
|
const callback = (args.length === 1 ? args[0] : args[1]);
|
|
775
906
|
(0, node_opcua_assert_1.assert)(typeof callback === "function");
|
|
776
907
|
debugLog("OPCUAServer#shutdown (timeout = ", timeout, ")");
|
|
777
|
-
/*
|
|
908
|
+
/* c8 ignore next */
|
|
778
909
|
if (!this.engine) {
|
|
779
910
|
return callback();
|
|
780
911
|
}
|
|
@@ -788,21 +919,27 @@ class OPCUAServer extends base_server_1.OPCUABaseServer {
|
|
|
788
919
|
this.engine.setServerState(node_opcua_common_1.ServerState.Shutdown);
|
|
789
920
|
const shutdownTime = new Date(Date.now() + timeout);
|
|
790
921
|
this.engine.setShutdownTime(shutdownTime);
|
|
791
|
-
debugLog("OPCUAServer is now un-registering itself from the discovery server "
|
|
792
|
-
this.registerServerManager
|
|
922
|
+
debugLog("OPCUAServer is now un-registering itself from the discovery server ", this.buildInfo);
|
|
923
|
+
if (!this.registerServerManager) {
|
|
924
|
+
callback(new Error("invalid register server manager"));
|
|
925
|
+
return;
|
|
926
|
+
}
|
|
927
|
+
this.registerServerManager
|
|
928
|
+
.stop()
|
|
793
929
|
.then(() => {
|
|
794
930
|
debugLog("OPCUAServer unregistered from discovery server successfully");
|
|
795
931
|
})
|
|
796
932
|
.catch((err) => {
|
|
797
933
|
debugLog("OPCUAServer unregistered from discovery server with err: ", err.message);
|
|
798
|
-
})
|
|
934
|
+
})
|
|
935
|
+
.finally(() => {
|
|
799
936
|
setTimeout(async () => {
|
|
800
937
|
await this.engine.shutdown();
|
|
801
938
|
debugLog("OPCUAServer#shutdown: started");
|
|
802
939
|
base_server_1.OPCUABaseServer.prototype.shutdown.call(this, (err1) => {
|
|
803
940
|
debugLog("OPCUAServer#shutdown: completed");
|
|
804
941
|
this.dispose();
|
|
805
|
-
callback(err1);
|
|
942
|
+
callback(err1 || undefined);
|
|
806
943
|
});
|
|
807
944
|
}, timeout);
|
|
808
945
|
});
|
|
@@ -818,19 +955,19 @@ class OPCUAServer extends base_server_1.OPCUABaseServer {
|
|
|
818
955
|
this.registerServerManager = undefined;
|
|
819
956
|
}
|
|
820
957
|
OPCUAServer.registry.unregister(this);
|
|
821
|
-
/*
|
|
958
|
+
/* c8 ignore next */
|
|
822
959
|
if (this.engine) {
|
|
823
960
|
this.engine.dispose();
|
|
824
961
|
}
|
|
825
962
|
}
|
|
826
963
|
raiseEvent(eventType, options) {
|
|
827
|
-
/*
|
|
964
|
+
/* c8 ignore next */
|
|
828
965
|
if (!this.engine.addressSpace) {
|
|
829
966
|
errorLog("addressSpace missing");
|
|
830
967
|
return;
|
|
831
968
|
}
|
|
832
969
|
const server = this.engine.addressSpace.findNode("Server");
|
|
833
|
-
/*
|
|
970
|
+
/* c8 ignore next */
|
|
834
971
|
if (!server) {
|
|
835
972
|
// xx throw new Error("OPCUAServer#raiseEvent : cannot find Server object");
|
|
836
973
|
return;
|
|
@@ -839,14 +976,14 @@ class OPCUAServer extends base_server_1.OPCUABaseServer {
|
|
|
839
976
|
if (typeof eventType === "string") {
|
|
840
977
|
eventTypeNode = this.engine.addressSpace.findEventType(eventType);
|
|
841
978
|
if (eventTypeNode) {
|
|
842
|
-
|
|
979
|
+
server.raiseEvent(eventTypeNode, options);
|
|
843
980
|
}
|
|
844
981
|
else {
|
|
845
982
|
console.warn(" cannot find event type ", eventType);
|
|
846
983
|
}
|
|
847
984
|
}
|
|
848
985
|
else {
|
|
849
|
-
|
|
986
|
+
server.raiseEvent(eventTypeNode, options);
|
|
850
987
|
}
|
|
851
988
|
}
|
|
852
989
|
/**
|
|
@@ -854,7 +991,7 @@ class OPCUAServer extends base_server_1.OPCUABaseServer {
|
|
|
854
991
|
* @private
|
|
855
992
|
*/
|
|
856
993
|
createSession(options) {
|
|
857
|
-
/*
|
|
994
|
+
/* c8 ignore next */
|
|
858
995
|
if (!this.engine) {
|
|
859
996
|
throw new Error("Internal Error");
|
|
860
997
|
}
|
|
@@ -890,64 +1027,73 @@ class OPCUAServer extends base_server_1.OPCUABaseServer {
|
|
|
890
1027
|
const result = (0, node_opcua_secure_channel_1.verifySignature)(serverCertificate, session.nonce, clientSignature, clientCertificate, securityPolicy);
|
|
891
1028
|
return result;
|
|
892
1029
|
}
|
|
893
|
-
isValidUserNameIdentityToken(channel,
|
|
1030
|
+
isValidUserNameIdentityToken(channel, _session, userTokenPolicy, userIdentityToken, _userTokenSignature, callback) {
|
|
894
1031
|
(0, node_opcua_assert_1.assert)(userIdentityToken instanceof node_opcua_service_session_1.UserNameIdentityToken);
|
|
895
1032
|
const securityPolicy = adjustSecurityPolicy(channel, userTokenPolicy.securityPolicyUri);
|
|
896
1033
|
if (securityPolicy === node_opcua_secure_channel_1.SecurityPolicy.None) {
|
|
897
|
-
|
|
1034
|
+
callback(null, node_opcua_status_code_1.StatusCodes.Good);
|
|
1035
|
+
return;
|
|
898
1036
|
}
|
|
899
1037
|
const cryptoFactory = (0, node_opcua_secure_channel_1.getCryptoFactory)(securityPolicy);
|
|
900
|
-
/*
|
|
1038
|
+
/* c8 ignore next */
|
|
901
1039
|
if (!cryptoFactory) {
|
|
902
|
-
|
|
1040
|
+
callback(null, node_opcua_status_code_1.StatusCodes.BadSecurityPolicyRejected);
|
|
1041
|
+
return;
|
|
903
1042
|
}
|
|
904
|
-
/*
|
|
1043
|
+
/* c8 ignore next */
|
|
905
1044
|
if (userIdentityToken.encryptionAlgorithm !== cryptoFactory.asymmetricEncryptionAlgorithm) {
|
|
906
1045
|
errorLog("invalid encryptionAlgorithm");
|
|
907
1046
|
errorLog("userTokenPolicy", userTokenPolicy.toString());
|
|
908
1047
|
errorLog("userTokenPolicy", userIdentityToken.toString());
|
|
909
|
-
|
|
1048
|
+
callback(null, node_opcua_status_code_1.StatusCodes.BadIdentityTokenInvalid);
|
|
1049
|
+
return;
|
|
910
1050
|
}
|
|
911
1051
|
const userName = userIdentityToken.userName;
|
|
912
1052
|
const password = userIdentityToken.password;
|
|
913
1053
|
if (!userName || !password) {
|
|
914
|
-
|
|
1054
|
+
callback(null, node_opcua_status_code_1.StatusCodes.BadIdentityTokenInvalid);
|
|
1055
|
+
return;
|
|
915
1056
|
}
|
|
916
|
-
|
|
1057
|
+
callback(null, node_opcua_status_code_1.StatusCodes.Good);
|
|
917
1058
|
}
|
|
918
1059
|
isValidX509IdentityToken(channel, session, userTokenPolicy, userIdentityToken, userTokenSignature, callback) {
|
|
919
1060
|
(0, node_opcua_assert_1.assert)(userIdentityToken instanceof node_opcua_service_session_1.X509IdentityToken);
|
|
920
1061
|
(0, node_opcua_assert_1.assert)(typeof callback === "function");
|
|
921
1062
|
const securityPolicy = adjustSecurityPolicy(channel, userTokenPolicy.securityPolicyUri);
|
|
922
1063
|
const cryptoFactory = (0, node_opcua_secure_channel_1.getCryptoFactory)(securityPolicy);
|
|
923
|
-
/*
|
|
1064
|
+
/* c8 ignore next */
|
|
924
1065
|
if (!cryptoFactory) {
|
|
925
|
-
|
|
1066
|
+
callback(null, node_opcua_status_code_1.StatusCodes.BadSecurityPolicyRejected);
|
|
1067
|
+
return;
|
|
926
1068
|
}
|
|
927
1069
|
if (!userTokenSignature || !userTokenSignature.signature) {
|
|
928
1070
|
this.raiseEvent("AuditCreateSessionEventType", {});
|
|
929
|
-
|
|
1071
|
+
callback(null, node_opcua_status_code_1.StatusCodes.BadUserSignatureInvalid);
|
|
1072
|
+
return;
|
|
930
1073
|
}
|
|
931
1074
|
if (userIdentityToken.policyId !== userTokenPolicy.policyId) {
|
|
932
1075
|
errorLog("invalid encryptionAlgorithm");
|
|
933
1076
|
errorLog("userTokenPolicy", userTokenPolicy.toString());
|
|
934
1077
|
errorLog("userTokenPolicy", userIdentityToken.toString());
|
|
935
|
-
|
|
1078
|
+
callback(null, node_opcua_status_code_1.StatusCodes.BadSecurityPolicyRejected);
|
|
1079
|
+
return;
|
|
936
1080
|
}
|
|
937
1081
|
const certificate = userIdentityToken.certificateData; /* as Certificate*/
|
|
938
1082
|
const nonce = session.nonce;
|
|
1083
|
+
if (!nonce || nonce.length === 0) {
|
|
1084
|
+
callback(null, node_opcua_status_code_1.StatusCodes.BadNonceInvalid);
|
|
1085
|
+
return;
|
|
1086
|
+
}
|
|
939
1087
|
const serverCertificate = this.getCertificate();
|
|
940
|
-
(0, node_opcua_assert_1.assert)(serverCertificate instanceof Buffer);
|
|
941
|
-
(0, node_opcua_assert_1.assert)(certificate instanceof Buffer, "expecting certificate to be a Buffer");
|
|
942
|
-
(0, node_opcua_assert_1.assert)(nonce instanceof Buffer, "expecting nonce to be a Buffer");
|
|
943
1088
|
(0, node_opcua_assert_1.assert)(userTokenSignature.signature instanceof Buffer, "expecting userTokenSignature to be a Buffer");
|
|
944
1089
|
// verify proof of possession by checking certificate signature & server nonce correctness
|
|
945
1090
|
if (!(0, node_opcua_secure_channel_1.verifySignature)(serverCertificate, nonce, userTokenSignature, certificate, securityPolicy)) {
|
|
946
|
-
|
|
1091
|
+
callback(null, node_opcua_status_code_1.StatusCodes.BadUserSignatureInvalid);
|
|
1092
|
+
return;
|
|
947
1093
|
}
|
|
948
1094
|
// verify if certificate is Valid
|
|
949
1095
|
this.userCertificateManager.checkCertificate(certificate, (err, certificateStatus) => {
|
|
950
|
-
/*
|
|
1096
|
+
/* c8 ignore next */
|
|
951
1097
|
if (err) {
|
|
952
1098
|
return callback(err);
|
|
953
1099
|
}
|
|
@@ -957,31 +1103,55 @@ class OPCUAServer extends base_server_1.OPCUABaseServer {
|
|
|
957
1103
|
break;
|
|
958
1104
|
case node_opcua_status_code_1.StatusCodes.BadCertificateUntrusted:
|
|
959
1105
|
this.raiseEvent("AuditCertificateUntrustedEventType", {
|
|
960
|
-
certificate: {
|
|
961
|
-
|
|
1106
|
+
certificate: {
|
|
1107
|
+
dataType: node_opcua_variant_1.DataType.ByteString,
|
|
1108
|
+
value: certificate
|
|
1109
|
+
},
|
|
1110
|
+
sourceName: {
|
|
1111
|
+
dataType: node_opcua_variant_1.DataType.String,
|
|
1112
|
+
value: "Security/Certificate"
|
|
1113
|
+
}
|
|
962
1114
|
});
|
|
963
1115
|
break;
|
|
964
1116
|
case node_opcua_status_code_1.StatusCodes.BadCertificateTimeInvalid:
|
|
965
1117
|
case node_opcua_status_code_1.StatusCodes.BadCertificateIssuerTimeInvalid:
|
|
966
1118
|
this.raiseEvent("AuditCertificateExpiredEventType", {
|
|
967
|
-
certificate: {
|
|
968
|
-
|
|
1119
|
+
certificate: {
|
|
1120
|
+
dataType: node_opcua_variant_1.DataType.ByteString,
|
|
1121
|
+
value: certificate
|
|
1122
|
+
},
|
|
1123
|
+
sourceName: {
|
|
1124
|
+
dataType: node_opcua_variant_1.DataType.String,
|
|
1125
|
+
value: "Security/Certificate"
|
|
1126
|
+
}
|
|
969
1127
|
});
|
|
970
1128
|
break;
|
|
971
1129
|
case node_opcua_status_code_1.StatusCodes.BadCertificateRevoked:
|
|
972
1130
|
case node_opcua_status_code_1.StatusCodes.BadCertificateRevocationUnknown:
|
|
973
1131
|
case node_opcua_status_code_1.StatusCodes.BadCertificateIssuerRevocationUnknown:
|
|
974
1132
|
this.raiseEvent("AuditCertificateRevokedEventType", {
|
|
975
|
-
certificate: {
|
|
976
|
-
|
|
1133
|
+
certificate: {
|
|
1134
|
+
dataType: node_opcua_variant_1.DataType.ByteString,
|
|
1135
|
+
value: certificate
|
|
1136
|
+
},
|
|
1137
|
+
sourceName: {
|
|
1138
|
+
dataType: node_opcua_variant_1.DataType.String,
|
|
1139
|
+
value: "Security/Certificate"
|
|
1140
|
+
}
|
|
977
1141
|
});
|
|
978
1142
|
break;
|
|
979
1143
|
case node_opcua_status_code_1.StatusCodes.BadCertificateIssuerUseNotAllowed:
|
|
980
1144
|
case node_opcua_status_code_1.StatusCodes.BadCertificateUseNotAllowed:
|
|
981
1145
|
case node_opcua_status_code_1.StatusCodes.BadSecurityChecksFailed:
|
|
982
1146
|
this.raiseEvent("AuditCertificateMismatchEventType", {
|
|
983
|
-
certificate: {
|
|
984
|
-
|
|
1147
|
+
certificate: {
|
|
1148
|
+
dataType: node_opcua_variant_1.DataType.ByteString,
|
|
1149
|
+
value: certificate
|
|
1150
|
+
},
|
|
1151
|
+
sourceName: {
|
|
1152
|
+
dataType: node_opcua_variant_1.DataType.String,
|
|
1153
|
+
value: "Security/Certificate"
|
|
1154
|
+
}
|
|
985
1155
|
});
|
|
986
1156
|
break;
|
|
987
1157
|
}
|
|
@@ -1020,6 +1190,10 @@ class OPCUAServer extends base_server_1.OPCUABaseServer {
|
|
|
1020
1190
|
// assert(this.isValidUserNameIdentityToken(channel, session, userTokenPolicy, userIdentityToken));
|
|
1021
1191
|
const securityPolicy = adjustSecurityPolicy(channel, userTokenPolicy.securityPolicyUri);
|
|
1022
1192
|
const userName = userIdentityToken.userName;
|
|
1193
|
+
if (!userName) {
|
|
1194
|
+
callback(new Error(" expecting a no null username"));
|
|
1195
|
+
return;
|
|
1196
|
+
}
|
|
1023
1197
|
let password = userIdentityToken.password;
|
|
1024
1198
|
// decrypt password if necessary
|
|
1025
1199
|
if (securityPolicy === node_opcua_secure_channel_1.SecurityPolicy.None) {
|
|
@@ -1029,16 +1203,20 @@ class OPCUAServer extends base_server_1.OPCUABaseServer {
|
|
|
1029
1203
|
else {
|
|
1030
1204
|
const serverPrivateKey = this.getPrivateKey();
|
|
1031
1205
|
const serverNonce = session.nonce;
|
|
1032
|
-
|
|
1206
|
+
if (!serverNonce) {
|
|
1207
|
+
callback(new Error(" expecting a no null nonce"));
|
|
1208
|
+
return;
|
|
1209
|
+
}
|
|
1033
1210
|
const cryptoFactory = (0, node_opcua_secure_channel_1.getCryptoFactory)(securityPolicy);
|
|
1034
|
-
/*
|
|
1211
|
+
/* c8 ignore next */
|
|
1035
1212
|
if (!cryptoFactory) {
|
|
1036
|
-
|
|
1213
|
+
callback(new Error(" Unsupported security Policy"));
|
|
1214
|
+
return;
|
|
1037
1215
|
}
|
|
1038
1216
|
const buff = cryptoFactory.asymmetricDecrypt(password, serverPrivateKey);
|
|
1039
1217
|
// server certificate may be invalid and asymmetricDecrypt may fail
|
|
1040
1218
|
if (!buff || buff.length < 4) {
|
|
1041
|
-
|
|
1219
|
+
setImmediate(() => callback(null, false));
|
|
1042
1220
|
return;
|
|
1043
1221
|
}
|
|
1044
1222
|
const length = buff.readUInt32LE(0) - serverNonce.length;
|
|
@@ -1054,7 +1232,7 @@ class OPCUAServer extends base_server_1.OPCUABaseServer {
|
|
|
1054
1232
|
*/
|
|
1055
1233
|
isValidUserIdentityToken(channel, session, userIdentityToken, userTokenSignature, endpointDescription, callback) {
|
|
1056
1234
|
(0, node_opcua_assert_1.assert)(typeof callback === "function");
|
|
1057
|
-
/*
|
|
1235
|
+
/* c8 ignore next */
|
|
1058
1236
|
if (!userIdentityToken) {
|
|
1059
1237
|
throw new Error("Invalid token");
|
|
1060
1238
|
}
|
|
@@ -1062,16 +1240,19 @@ class OPCUAServer extends base_server_1.OPCUABaseServer {
|
|
|
1062
1240
|
const userTokenPolicy = findUserTokenByPolicy(endpointDescription, userTokenType, userIdentityToken.policyId);
|
|
1063
1241
|
if (!userTokenPolicy) {
|
|
1064
1242
|
// cannot find token with this policyId
|
|
1065
|
-
|
|
1243
|
+
callback(null, node_opcua_status_code_1.StatusCodes.BadIdentityTokenInvalid);
|
|
1244
|
+
return;
|
|
1066
1245
|
}
|
|
1067
1246
|
//
|
|
1068
1247
|
if (userIdentityToken instanceof node_opcua_service_session_1.UserNameIdentityToken) {
|
|
1069
|
-
|
|
1248
|
+
this.isValidUserNameIdentityToken(channel, session, userTokenPolicy, userIdentityToken, userTokenSignature, callback);
|
|
1249
|
+
return;
|
|
1070
1250
|
}
|
|
1071
1251
|
if (userIdentityToken instanceof node_opcua_service_session_1.X509IdentityToken) {
|
|
1072
|
-
|
|
1252
|
+
this.isValidX509IdentityToken(channel, session, userTokenPolicy, userIdentityToken, userTokenSignature, callback);
|
|
1253
|
+
return;
|
|
1073
1254
|
}
|
|
1074
|
-
|
|
1255
|
+
callback(null, node_opcua_status_code_1.StatusCodes.Good);
|
|
1075
1256
|
}
|
|
1076
1257
|
/**
|
|
1077
1258
|
*
|
|
@@ -1087,18 +1268,20 @@ class OPCUAServer extends base_server_1.OPCUABaseServer {
|
|
|
1087
1268
|
(0, node_opcua_assert_1.assert)(typeof callback === "function");
|
|
1088
1269
|
const userTokenType = getTokenType(userIdentityToken);
|
|
1089
1270
|
const userTokenPolicy = findUserTokenByPolicy(session.getEndpointDescription(), userTokenType, userIdentityToken.policyId);
|
|
1090
|
-
/**
|
|
1271
|
+
/** c8 ignore next */
|
|
1091
1272
|
if (!userTokenPolicy) {
|
|
1092
|
-
|
|
1273
|
+
callback(null, false);
|
|
1274
|
+
return;
|
|
1093
1275
|
}
|
|
1094
1276
|
// find if a userToken exists
|
|
1095
1277
|
if (userIdentityToken instanceof node_opcua_service_session_1.UserNameIdentityToken) {
|
|
1096
|
-
|
|
1278
|
+
this.userNameIdentityTokenAuthenticateUser(channel, session, userTokenPolicy, userIdentityToken, callback);
|
|
1279
|
+
return;
|
|
1097
1280
|
}
|
|
1098
|
-
|
|
1281
|
+
setImmediate(callback.bind(null, null, true));
|
|
1099
1282
|
}
|
|
1100
1283
|
makeServerNonce() {
|
|
1101
|
-
return (0,
|
|
1284
|
+
return (0, node_crypto_1.randomBytes)(32);
|
|
1102
1285
|
}
|
|
1103
1286
|
// session services
|
|
1104
1287
|
// eslint-disable-next-line max-statements
|
|
@@ -1146,12 +1329,12 @@ class OPCUAServer extends base_server_1.OPCUABaseServer {
|
|
|
1146
1329
|
// its application instance Certificate in the response.
|
|
1147
1330
|
if (!request.clientNonce || request.clientNonce.length < 32) {
|
|
1148
1331
|
if (channel.securityMode !== node_opcua_secure_channel_1.MessageSecurityMode.None) {
|
|
1149
|
-
errorLog(chalk_1.default.red("SERVER with secure connection: Missing or invalid client Nonce "), request.clientNonce
|
|
1332
|
+
errorLog(chalk_1.default.red("SERVER with secure connection: Missing or invalid client Nonce "), request.clientNonce?.toString("hex"));
|
|
1150
1333
|
return rejectConnection(this, node_opcua_status_code_1.StatusCodes.BadNonceInvalid);
|
|
1151
1334
|
}
|
|
1152
1335
|
}
|
|
1153
1336
|
if ((0, node_opcua_secure_channel_1.nonceAlreadyBeenUsed)(request.clientNonce)) {
|
|
1154
|
-
errorLog(chalk_1.default.red("SERVER with secure connection: Nonce has already been used"), request.clientNonce
|
|
1337
|
+
errorLog(chalk_1.default.red("SERVER with secure connection: Nonce has already been used"), request.clientNonce?.toString("hex"));
|
|
1155
1338
|
return rejectConnection(this, node_opcua_status_code_1.StatusCodes.BadNonceInvalid);
|
|
1156
1339
|
}
|
|
1157
1340
|
// check application spoofing
|
|
@@ -1193,7 +1376,7 @@ class OPCUAServer extends base_server_1.OPCUABaseServer {
|
|
|
1193
1376
|
const serverCertificateChain = this.getCertificateChain();
|
|
1194
1377
|
const hasEncryption = true;
|
|
1195
1378
|
// If the securityPolicyUri is None and none of the UserTokenPolicies requires encryption
|
|
1196
|
-
if (session.channel
|
|
1379
|
+
if (session.channel?.securityMode === node_opcua_secure_channel_1.MessageSecurityMode.None) {
|
|
1197
1380
|
// ToDo: Check that none of our insecure endpoint has a a UserTokenPolicy that require encryption
|
|
1198
1381
|
// and set hasEncryption = false under this condition
|
|
1199
1382
|
}
|
|
@@ -1224,7 +1407,7 @@ class OPCUAServer extends base_server_1.OPCUABaseServer {
|
|
|
1224
1407
|
// securityPolicyUri, userIdentityTokens, transportProfileUri and securityLevel with all
|
|
1225
1408
|
// other parameters set to null. Only the recommended parameters shall be verified by
|
|
1226
1409
|
// the client.
|
|
1227
|
-
serverEndpoints: _serverEndpointsForCreateSessionResponse(this, session.endpoint
|
|
1410
|
+
serverEndpoints: _serverEndpointsForCreateSessionResponse(this, session.endpoint?.endpointUrl || "", request.serverUri),
|
|
1228
1411
|
// This parameter is deprecated and the array shall be empty.
|
|
1229
1412
|
serverSoftwareCertificates: null,
|
|
1230
1413
|
// This is a signature generated with the private key associated with the
|
|
@@ -1245,7 +1428,7 @@ class OPCUAServer extends base_server_1.OPCUABaseServer {
|
|
|
1245
1428
|
(0, node_opcua_assert_1.assert)(typeof reason === "string");
|
|
1246
1429
|
if (this.isAuditing) {
|
|
1247
1430
|
(0, node_opcua_assert_1.assert)(reason === "Timeout" || reason === "Terminated" || reason === "CloseSession" || reason === "Forcing");
|
|
1248
|
-
const sourceName =
|
|
1431
|
+
const sourceName = `Session/${reason}`;
|
|
1249
1432
|
this.raiseEvent("AuditSessionEventType", {
|
|
1250
1433
|
/* part 5 - 6.4.3 AuditEventType */
|
|
1251
1434
|
actionTimeStamp: { dataType: "DateTime", value: new Date() },
|
|
@@ -1283,15 +1466,24 @@ class OPCUAServer extends base_server_1.OPCUABaseServer {
|
|
|
1283
1466
|
// identifier in all AuditEvents related to the Session Service Set (AuditCreateSessionEventType,
|
|
1284
1467
|
// AuditActivateSessionEventType and their subtypes) and the SecureChannel Service Set
|
|
1285
1468
|
// (AuditChannelEventType and its subtypes
|
|
1286
|
-
secureChannelId: {
|
|
1469
|
+
secureChannelId: {
|
|
1470
|
+
dataType: "String",
|
|
1471
|
+
value: session.channel?.channelId?.toString() ?? ""
|
|
1472
|
+
},
|
|
1287
1473
|
// Duration
|
|
1288
|
-
revisedSessionTimeout: {
|
|
1474
|
+
revisedSessionTimeout: {
|
|
1475
|
+
dataType: "Duration",
|
|
1476
|
+
value: session.sessionTimeout
|
|
1477
|
+
},
|
|
1289
1478
|
// clientCertificate
|
|
1290
|
-
clientCertificate: {
|
|
1479
|
+
clientCertificate: {
|
|
1480
|
+
dataType: "ByteString",
|
|
1481
|
+
value: session.channel?.clientCertificate ?? null
|
|
1482
|
+
},
|
|
1291
1483
|
// clientCertificateThumbprint
|
|
1292
1484
|
clientCertificateThumbprint: {
|
|
1293
1485
|
dataType: "String",
|
|
1294
|
-
value: thumbprint(session.channel
|
|
1486
|
+
value: thumbprint(session.channel?.clientCertificate)
|
|
1295
1487
|
}
|
|
1296
1488
|
});
|
|
1297
1489
|
}
|
|
@@ -1329,16 +1521,18 @@ class OPCUAServer extends base_server_1.OPCUABaseServer {
|
|
|
1329
1521
|
server.engine.incrementRejectedSessionCount();
|
|
1330
1522
|
server.engine.incrementSecurityRejectedSessionCount();
|
|
1331
1523
|
}
|
|
1332
|
-
const response1 = new node_opcua_service_session_1.ActivateSessionResponse({
|
|
1524
|
+
const response1 = new node_opcua_service_session_1.ActivateSessionResponse({
|
|
1525
|
+
responseHeader: { serviceResult: statusCode }
|
|
1526
|
+
});
|
|
1333
1527
|
channel.send_response("MSG", response1, message);
|
|
1334
1528
|
}
|
|
1335
|
-
|
|
1336
|
-
/* istanbul ignore next */
|
|
1529
|
+
/* c8 ignore next */
|
|
1337
1530
|
if (!session) {
|
|
1338
1531
|
// this may happen when the server has been restarted and a client tries to reconnect, thinking
|
|
1339
1532
|
// that the previous session may still be active
|
|
1340
1533
|
debugLog(chalk_1.default.yellow.bold(" Bad Session in _on_ActivateSessionRequest"), authenticationToken.toString());
|
|
1341
|
-
|
|
1534
|
+
rejectConnection(this, node_opcua_status_code_1.StatusCodes.BadSessionIdInvalid);
|
|
1535
|
+
return;
|
|
1342
1536
|
}
|
|
1343
1537
|
// tslint:disable-next-line: no-unused-expression
|
|
1344
1538
|
session.keepAlive ? session.keepAlive() : void 0;
|
|
@@ -1350,8 +1544,9 @@ class OPCUAServer extends base_server_1.OPCUABaseServer {
|
|
|
1350
1544
|
if (!channel_has_session(channel, session)) {
|
|
1351
1545
|
// it looks like session activation is being using a channel that is not the
|
|
1352
1546
|
// one that have been used to create the session
|
|
1353
|
-
errorLog(
|
|
1354
|
-
|
|
1547
|
+
errorLog(` channel.sessionTokens === ${Object.keys(channel.sessionTokens).join(" ")}`);
|
|
1548
|
+
rejectConnection(this, node_opcua_status_code_1.StatusCodes.BadSessionNotActivated);
|
|
1549
|
+
return;
|
|
1355
1550
|
}
|
|
1356
1551
|
}
|
|
1357
1552
|
// OpcUA 1.02 part 3 $5.6.3.1 ActiveSession Set page 29
|
|
@@ -1359,41 +1554,51 @@ class OPCUAServer extends base_server_1.OPCUABaseServer {
|
|
|
1359
1554
|
// case then the Server shall verify that the Certificate the Client used to create the new
|
|
1360
1555
|
// SecureChannel is the same as the Certificate used to create the original SecureChannel.
|
|
1361
1556
|
if (session.status === "active") {
|
|
1362
|
-
if (session.channel
|
|
1363
|
-
warningLog(" Session ", session.sessionName, " is being transferred from channel", chalk_1.default.cyan(session.channel
|
|
1557
|
+
if (session.channel?.channelId !== channel.channelId) {
|
|
1558
|
+
warningLog(" Session ", session.sessionName, " is being transferred from channel", chalk_1.default.cyan(session.channel?.channelId?.toString()), " to channel ", chalk_1.default.cyan(channel.channelId?.toString()));
|
|
1364
1559
|
// session is being reassigned to a new Channel,
|
|
1365
1560
|
// we shall verify that the certificate used to create the Session is the same as the current
|
|
1366
1561
|
// channel certificate.
|
|
1367
|
-
const old_channel_cert_thumbprint = thumbprint(session.channel
|
|
1562
|
+
const old_channel_cert_thumbprint = thumbprint(session.channel?.clientCertificate);
|
|
1368
1563
|
const new_channel_cert_thumbprint = thumbprint(channel.clientCertificate);
|
|
1369
1564
|
if (old_channel_cert_thumbprint !== new_channel_cert_thumbprint) {
|
|
1370
|
-
|
|
1565
|
+
rejectConnection(this, node_opcua_status_code_1.StatusCodes.BadNoValidCertificates); // not sure about this code !
|
|
1566
|
+
return;
|
|
1371
1567
|
}
|
|
1372
1568
|
// ... In addition the Server shall verify that the Client supplied a UserIdentityToken that is
|
|
1373
1569
|
// identical to the token currently associated with the Session reassign session to new channel.
|
|
1374
1570
|
if (!sameIdentityToken(session.userIdentityToken, request.userIdentityToken)) {
|
|
1375
|
-
|
|
1571
|
+
rejectConnection(this, node_opcua_status_code_1.StatusCodes.BadIdentityChangeNotSupported); // not sure about this code !
|
|
1572
|
+
return;
|
|
1376
1573
|
}
|
|
1377
1574
|
}
|
|
1378
1575
|
}
|
|
1379
1576
|
else if (session.status === "screwed") {
|
|
1380
1577
|
// session has been used before being activated => this should be detected and session should be dismissed.
|
|
1381
|
-
|
|
1578
|
+
rejectConnection(this, node_opcua_status_code_1.StatusCodes.BadSessionClosed);
|
|
1579
|
+
return;
|
|
1382
1580
|
}
|
|
1383
1581
|
else if (session.status === "closed") {
|
|
1384
1582
|
warningLog(chalk_1.default.yellow.bold(" Bad Session Closed in _on_ActivateSessionRequest"), authenticationToken.toString());
|
|
1385
|
-
|
|
1583
|
+
rejectConnection(this, node_opcua_status_code_1.StatusCodes.BadSessionClosed);
|
|
1584
|
+
return;
|
|
1386
1585
|
}
|
|
1387
1586
|
// verify clientSignature provided by the client
|
|
1388
1587
|
if (!this.verifyClientSignature(session, channel, request.clientSignature)) {
|
|
1389
|
-
|
|
1588
|
+
rejectConnection(this, node_opcua_status_code_1.StatusCodes.BadApplicationSignatureInvalid);
|
|
1589
|
+
return;
|
|
1590
|
+
}
|
|
1591
|
+
const endpoint = session.endpoint;
|
|
1592
|
+
if (!endpoint) {
|
|
1593
|
+
rejectConnection(this, node_opcua_status_code_1.StatusCodes.BadSessionIdInvalid);
|
|
1594
|
+
return;
|
|
1390
1595
|
}
|
|
1391
1596
|
// userIdentityToken may be missing , assume anonymous access then
|
|
1392
|
-
request.userIdentityToken = request.userIdentityToken || createAnonymousIdentityToken(
|
|
1597
|
+
request.userIdentityToken = request.userIdentityToken || createAnonymousIdentityToken(endpoint);
|
|
1393
1598
|
// check request.userIdentityToken is correct ( expected type and correctly formed)
|
|
1394
|
-
this.isValidUserIdentityToken(channel, session, request.userIdentityToken, request.userTokenSignature,
|
|
1599
|
+
this.isValidUserIdentityToken(channel, session, request.userIdentityToken, request.userTokenSignature, endpoint, (_err, statusCode) => {
|
|
1395
1600
|
if (!statusCode || statusCode.isNotGood()) {
|
|
1396
|
-
/*
|
|
1601
|
+
/* c8 ignore next */
|
|
1397
1602
|
if (!(statusCode && statusCode instanceof node_opcua_status_code_1.StatusCode)) {
|
|
1398
1603
|
return rejectConnection(this, node_opcua_status_code_1.StatusCodes.BadCertificateInvalid);
|
|
1399
1604
|
}
|
|
@@ -1401,7 +1606,7 @@ class OPCUAServer extends base_server_1.OPCUABaseServer {
|
|
|
1401
1606
|
}
|
|
1402
1607
|
// check if user access is granted
|
|
1403
1608
|
this.isUserAuthorized(channel, session, request.userIdentityToken, (err1, authorized) => {
|
|
1404
|
-
/*
|
|
1609
|
+
/* c8 ignore next */
|
|
1405
1610
|
if (err1) {
|
|
1406
1611
|
return rejectConnection(this, node_opcua_status_code_1.StatusCodes.BadInternalError);
|
|
1407
1612
|
}
|
|
@@ -1418,7 +1623,9 @@ class OPCUAServer extends base_server_1.OPCUABaseServer {
|
|
|
1418
1623
|
// serverNonce each time the ActivateSession Service is called.
|
|
1419
1624
|
session.nonce = this.makeServerNonce();
|
|
1420
1625
|
session.status = "active";
|
|
1421
|
-
response = new node_opcua_service_session_1.ActivateSessionResponse({
|
|
1626
|
+
const response = new node_opcua_service_session_1.ActivateSessionResponse({
|
|
1627
|
+
serverNonce: session.nonce
|
|
1628
|
+
});
|
|
1422
1629
|
channel.send_response("MSG", response, message);
|
|
1423
1630
|
// send OPCUA Event Notification
|
|
1424
1631
|
// see part 5 : 6.4.3 AuditEventType
|
|
@@ -1447,7 +1654,12 @@ class OPCUAServer extends base_server_1.OPCUABaseServer {
|
|
|
1447
1654
|
// --- check that provided session matches session attached to channel
|
|
1448
1655
|
if (channel.channelId !== session.channelId) {
|
|
1449
1656
|
if (!(request instanceof node_opcua_service_session_1.ActivateSessionRequest)) {
|
|
1450
|
-
|
|
1657
|
+
// Note: PublishRequests arriving on the new channel before
|
|
1658
|
+
// ActivateSession completes the session transfer are expected
|
|
1659
|
+
// transient occurrences, not errors worth logging.
|
|
1660
|
+
if (request.constructor.name !== "PublishRequest") {
|
|
1661
|
+
errorLog(chalk_1.default.red.bgWhite(`ERROR: channel.channelId !== session.channelId on processing request ${request.constructor.name}`), channel.channelId, session.channelId);
|
|
1662
|
+
}
|
|
1451
1663
|
}
|
|
1452
1664
|
message.session_statusCode = node_opcua_status_code_1.StatusCodes.BadSecureChannelIdInvalid;
|
|
1453
1665
|
}
|
|
@@ -1487,12 +1699,12 @@ class OPCUAServer extends base_server_1.OPCUABaseServer {
|
|
|
1487
1699
|
}
|
|
1488
1700
|
catch (err) {
|
|
1489
1701
|
warningLog(err);
|
|
1490
|
-
//
|
|
1491
|
-
if (
|
|
1492
|
-
//
|
|
1702
|
+
// c8 ignore next
|
|
1703
|
+
if (node_util_1.types.isNativeError(err)) {
|
|
1704
|
+
// c8 ignore next
|
|
1493
1705
|
errorLog("Internal error in issuing response\nplease contact support@sterfive.com", message.request.toString(), "\n", response1.toString());
|
|
1494
1706
|
}
|
|
1495
|
-
//
|
|
1707
|
+
// c8 ignore next
|
|
1496
1708
|
throw err;
|
|
1497
1709
|
}
|
|
1498
1710
|
}
|
|
@@ -1502,12 +1714,14 @@ class OPCUAServer extends base_server_1.OPCUABaseServer {
|
|
|
1502
1714
|
}
|
|
1503
1715
|
return g_sendError(channel, message, ResponseClass, statusCode);
|
|
1504
1716
|
}
|
|
1505
|
-
|
|
1506
|
-
/* istanbul ignore next */
|
|
1717
|
+
/* c8 ignore next */
|
|
1507
1718
|
if (!message.session || message.session_statusCode !== node_opcua_status_code_1.StatusCodes.Good) {
|
|
1508
|
-
const
|
|
1509
|
-
|
|
1510
|
-
|
|
1719
|
+
const sessionStatusCode = message.session_statusCode ?? node_opcua_status_code_1.StatusCodes.BadInternalError;
|
|
1720
|
+
const errMessage = `=>${sessionStatusCode.toString()}`;
|
|
1721
|
+
const response = new node_opcua_types_1.ServiceFault({
|
|
1722
|
+
responseHeader: { serviceResult: sessionStatusCode }
|
|
1723
|
+
});
|
|
1724
|
+
debugLog(chalk_1.default.red.bold(errMessage), chalk_1.default.yellow(sessionStatusCode.toString()), response.constructor.name);
|
|
1511
1725
|
return sendResponse(response);
|
|
1512
1726
|
}
|
|
1513
1727
|
(0, node_opcua_assert_1.assert)(message.session_statusCode.isGood());
|
|
@@ -1545,7 +1759,7 @@ class OPCUAServer extends base_server_1.OPCUABaseServer {
|
|
|
1545
1759
|
async _apply_on_Subscription(ResponseClass, message, channel, actionToPerform) {
|
|
1546
1760
|
(0, node_opcua_assert_1.assert)(typeof actionToPerform === "function");
|
|
1547
1761
|
const request = message.request;
|
|
1548
|
-
(0, node_opcua_assert_1.assert)(Object.
|
|
1762
|
+
(0, node_opcua_assert_1.assert)(Object.hasOwn(request, "subscriptionId"));
|
|
1549
1763
|
this._apply_on_SessionObject(ResponseClass, message, channel, async (session, sendResponse, sendError) => {
|
|
1550
1764
|
const subscription = session.getSubscription(request.subscriptionId);
|
|
1551
1765
|
if (!subscription) {
|
|
@@ -1558,7 +1772,7 @@ class OPCUAServer extends base_server_1.OPCUABaseServer {
|
|
|
1558
1772
|
_apply_on_SubscriptionIds(ResponseClass, message, channel, actionToPerform) {
|
|
1559
1773
|
(0, node_opcua_assert_1.assert)(typeof actionToPerform === "function");
|
|
1560
1774
|
const request = message.request;
|
|
1561
|
-
(0, node_opcua_assert_1.assert)(Object.
|
|
1775
|
+
(0, node_opcua_assert_1.assert)(Object.hasOwn(request, "subscriptionIds"));
|
|
1562
1776
|
this._apply_on_SessionObject(ResponseClass, message, channel, async (session, sendResponse, sendError) => {
|
|
1563
1777
|
const subscriptionIds = request.subscriptionIds;
|
|
1564
1778
|
if (!request.subscriptionIds || request.subscriptionIds.length === 0) {
|
|
@@ -1583,7 +1797,7 @@ class OPCUAServer extends base_server_1.OPCUABaseServer {
|
|
|
1583
1797
|
}
|
|
1584
1798
|
_apply_on_Subscriptions(ResponseClass, message, channel, actionToPerform) {
|
|
1585
1799
|
this._apply_on_SubscriptionIds(ResponseClass, message, channel, async (session, subscriptionId) => {
|
|
1586
|
-
/*
|
|
1800
|
+
/* c8 ignore next */
|
|
1587
1801
|
if (isSubscriptionIdInvalid(subscriptionId)) {
|
|
1588
1802
|
return node_opcua_status_code_1.StatusCodes.BadSubscriptionIdInvalid;
|
|
1589
1803
|
}
|
|
@@ -1600,7 +1814,10 @@ class OPCUAServer extends base_server_1.OPCUABaseServer {
|
|
|
1600
1814
|
if (session) {
|
|
1601
1815
|
const subscriptions = session.publishEngine.subscriptions;
|
|
1602
1816
|
for (const subscription of subscriptions) {
|
|
1603
|
-
|
|
1817
|
+
const onDeleteFn = this.options.onDeleteMonitoredItem;
|
|
1818
|
+
await subscription.applyOnMonitoredItem(async (monitoredItem) => {
|
|
1819
|
+
await onDeleteFn(subscription, monitoredItem);
|
|
1820
|
+
});
|
|
1604
1821
|
}
|
|
1605
1822
|
}
|
|
1606
1823
|
}
|
|
@@ -1614,7 +1831,6 @@ class OPCUAServer extends base_server_1.OPCUABaseServer {
|
|
|
1614
1831
|
_on_CloseSessionRequest(message, channel) {
|
|
1615
1832
|
const request = message.request;
|
|
1616
1833
|
(0, node_opcua_assert_1.assert)(request instanceof node_opcua_service_session_1.CloseSessionRequest);
|
|
1617
|
-
let response;
|
|
1618
1834
|
message.session_statusCode = node_opcua_status_code_1.StatusCodes.Good;
|
|
1619
1835
|
function sendError(statusCode) {
|
|
1620
1836
|
return g_sendError(channel, message, node_opcua_service_session_1.CloseSessionResponse, statusCode);
|
|
@@ -1627,20 +1843,21 @@ class OPCUAServer extends base_server_1.OPCUABaseServer {
|
|
|
1627
1843
|
// });
|
|
1628
1844
|
const session = message.session;
|
|
1629
1845
|
if (!session) {
|
|
1630
|
-
|
|
1846
|
+
sendError(node_opcua_status_code_1.StatusCodes.BadSessionIdInvalid);
|
|
1847
|
+
return;
|
|
1631
1848
|
}
|
|
1632
1849
|
// session has been created but not activated !
|
|
1633
|
-
const
|
|
1850
|
+
const _wasNotActivated = session.status === "new";
|
|
1634
1851
|
(async () => {
|
|
1635
1852
|
try {
|
|
1636
1853
|
await this._closeSession(request.requestHeader.authenticationToken, request.deleteSubscriptions, "CloseSession");
|
|
1637
1854
|
// if (false && wasNotActivated) {
|
|
1638
1855
|
// return sendError(StatusCodes.BadSessionNotActivated);
|
|
1639
1856
|
// }
|
|
1640
|
-
response = new node_opcua_service_session_1.CloseSessionResponse({});
|
|
1857
|
+
const response = new node_opcua_service_session_1.CloseSessionResponse({});
|
|
1641
1858
|
sendResponse(response);
|
|
1642
1859
|
}
|
|
1643
|
-
catch (
|
|
1860
|
+
catch (_err) {
|
|
1644
1861
|
sendError(node_opcua_status_code_1.StatusCodes.BadInternalError);
|
|
1645
1862
|
}
|
|
1646
1863
|
})();
|
|
@@ -1659,7 +1876,11 @@ class OPCUAServer extends base_server_1.OPCUABaseServer {
|
|
|
1659
1876
|
let response;
|
|
1660
1877
|
// test view
|
|
1661
1878
|
if (request.view && !request.view.viewId.isEmpty()) {
|
|
1662
|
-
|
|
1879
|
+
const addressSpace = this.engine.addressSpace;
|
|
1880
|
+
if (!addressSpace) {
|
|
1881
|
+
return sendError(node_opcua_status_code_1.StatusCodes.BadInternalError);
|
|
1882
|
+
}
|
|
1883
|
+
let theView = addressSpace.findNode(request.view.viewId);
|
|
1663
1884
|
if (theView && theView.nodeClass !== node_opcua_data_model_1.NodeClass.View) {
|
|
1664
1885
|
// Error: theView is not a View
|
|
1665
1886
|
diagnostic.localizedText = { text: "Expecting a view here" };
|
|
@@ -1681,9 +1902,9 @@ class OPCUAServer extends base_server_1.OPCUABaseServer {
|
|
|
1681
1902
|
const requestedMaxReferencesPerNode = Math.min(9876, request.requestedMaxReferencesPerNode);
|
|
1682
1903
|
(0, node_opcua_assert_1.assert)(request.nodesToBrowse[0].schema.name === "BrowseDescription");
|
|
1683
1904
|
const context = session.sessionContext;
|
|
1684
|
-
const browseAll = (
|
|
1685
|
-
const f = (0,
|
|
1686
|
-
f(request.nodesToBrowse, context, callack);
|
|
1905
|
+
const browseAll = (_nodesToBrowse, callack) => {
|
|
1906
|
+
const f = (0, node_util_1.callbackify)(this.engine.browseWithAutomaticExpansion).bind(this.engine);
|
|
1907
|
+
f(request.nodesToBrowse ?? [], context, callack);
|
|
1687
1908
|
};
|
|
1688
1909
|
// handle continuation point and requestedMaxReferencesPerNode
|
|
1689
1910
|
const maxBrowseContinuationPoints = this.engine.serverCapabilities.maxBrowseContinuationPoints;
|
|
@@ -1693,7 +1914,7 @@ class OPCUAServer extends base_server_1.OPCUABaseServer {
|
|
|
1693
1914
|
continuationPointManager: session.continuationPointManager,
|
|
1694
1915
|
requestedMaxReferencesPerNode,
|
|
1695
1916
|
maxBrowseContinuationPoints
|
|
1696
|
-
}, request.nodesToBrowse, (
|
|
1917
|
+
}, request.nodesToBrowse, (_err, results) => {
|
|
1697
1918
|
if (!results) {
|
|
1698
1919
|
return sendError(node_opcua_status_code_1.StatusCodes.BadInternalError);
|
|
1699
1920
|
}
|
|
@@ -1758,17 +1979,17 @@ class OPCUAServer extends base_server_1.OPCUABaseServer {
|
|
|
1758
1979
|
nodeToRead.nodeId = session.resolveRegisteredNode(nodeToRead.nodeId);
|
|
1759
1980
|
}
|
|
1760
1981
|
// ask for a refresh of asynchronous variables
|
|
1761
|
-
this.engine.refreshValues(request.nodesToRead, request.maxAge, (
|
|
1982
|
+
this.engine.refreshValues(request.nodesToRead, request.maxAge, (_err) => {
|
|
1762
1983
|
this.engine.read(context, request).then((results) => {
|
|
1763
1984
|
(0, node_opcua_assert_1.assert)(results[0].schema.name === "DataValue");
|
|
1764
|
-
(0, node_opcua_assert_1.assert)(results.length === request.nodesToRead
|
|
1985
|
+
(0, node_opcua_assert_1.assert)(results.length === request.nodesToRead?.length);
|
|
1765
1986
|
const response = new node_opcua_service_read_1.ReadResponse({
|
|
1766
1987
|
diagnosticInfos: undefined,
|
|
1767
1988
|
results: undefined
|
|
1768
1989
|
});
|
|
1769
1990
|
// set it here for performance
|
|
1770
1991
|
response.results = results;
|
|
1771
|
-
(0, node_opcua_assert_1.assert)(response.diagnosticInfos
|
|
1992
|
+
(0, node_opcua_assert_1.assert)(response.diagnosticInfos?.length === 0);
|
|
1772
1993
|
sendResponse(response);
|
|
1773
1994
|
});
|
|
1774
1995
|
});
|
|
@@ -1779,7 +2000,6 @@ class OPCUAServer extends base_server_1.OPCUABaseServer {
|
|
|
1779
2000
|
const request = message.request;
|
|
1780
2001
|
(0, node_opcua_assert_1.assert)(request instanceof node_opcua_service_history_1.HistoryReadRequest);
|
|
1781
2002
|
this._apply_on_SessionObject(node_opcua_service_history_1.HistoryReadResponse, message, channel, (session, sendResponse, sendError) => {
|
|
1782
|
-
let response;
|
|
1783
2003
|
const timestampsToReturn = request.timestampsToReturn;
|
|
1784
2004
|
if (timestampsToReturn === node_opcua_service_read_1.TimestampsToReturn.Invalid) {
|
|
1785
2005
|
return sendError(node_opcua_status_code_1.StatusCodes.BadTimestampsToReturnInvalid);
|
|
@@ -1814,15 +2034,15 @@ class OPCUAServer extends base_server_1.OPCUABaseServer {
|
|
|
1814
2034
|
.historyRead(context, request)
|
|
1815
2035
|
.then((results) => {
|
|
1816
2036
|
(0, node_opcua_assert_1.assert)(results[0].schema.name === "HistoryReadResult");
|
|
1817
|
-
(0, node_opcua_assert_1.assert)(results.length === request.nodesToRead
|
|
1818
|
-
response = new node_opcua_service_history_1.HistoryReadResponse({
|
|
2037
|
+
(0, node_opcua_assert_1.assert)(results.length === request.nodesToRead?.length);
|
|
2038
|
+
const response = new node_opcua_service_history_1.HistoryReadResponse({
|
|
1819
2039
|
diagnosticInfos: undefined,
|
|
1820
2040
|
results
|
|
1821
2041
|
});
|
|
1822
|
-
(0, node_opcua_assert_1.assert)(response.diagnosticInfos
|
|
2042
|
+
(0, node_opcua_assert_1.assert)(response.diagnosticInfos?.length === 0);
|
|
1823
2043
|
sendResponse(response);
|
|
1824
2044
|
})
|
|
1825
|
-
.catch((
|
|
2045
|
+
.catch((_err) => {
|
|
1826
2046
|
return sendError(node_opcua_status_code_1.StatusCodes.BadHistoryOperationInvalid);
|
|
1827
2047
|
});
|
|
1828
2048
|
});
|
|
@@ -1847,7 +2067,6 @@ class OPCUAServer extends base_server_1.OPCUABaseServer {
|
|
|
1847
2067
|
(0, node_opcua_assert_1.assert)(request instanceof node_opcua_service_write_1.WriteRequest);
|
|
1848
2068
|
(0, node_opcua_assert_1.assert)(!request.nodesToWrite || Array.isArray(request.nodesToWrite));
|
|
1849
2069
|
this._apply_on_SessionObject(node_opcua_service_write_1.WriteResponse, message, channel, (session, sendResponse, sendError) => {
|
|
1850
|
-
let response;
|
|
1851
2070
|
if (!request.nodesToWrite || request.nodesToWrite.length === 0) {
|
|
1852
2071
|
return sendError(node_opcua_status_code_1.StatusCodes.BadNothingToDo);
|
|
1853
2072
|
}
|
|
@@ -1865,8 +2084,8 @@ class OPCUAServer extends base_server_1.OPCUABaseServer {
|
|
|
1865
2084
|
this.engine
|
|
1866
2085
|
.write(context, request.nodesToWrite)
|
|
1867
2086
|
.then((results) => {
|
|
1868
|
-
(0, node_opcua_assert_1.assert)(results
|
|
1869
|
-
response = new node_opcua_service_write_1.WriteResponse({
|
|
2087
|
+
(0, node_opcua_assert_1.assert)(results?.length === request.nodesToWrite?.length);
|
|
2088
|
+
const response = new node_opcua_service_write_1.WriteResponse({
|
|
1870
2089
|
diagnosticInfos: undefined,
|
|
1871
2090
|
results
|
|
1872
2091
|
});
|
|
@@ -1882,6 +2101,10 @@ class OPCUAServer extends base_server_1.OPCUABaseServer {
|
|
|
1882
2101
|
_on_CreateSubscriptionRequest(message, channel) {
|
|
1883
2102
|
const engine = this.engine;
|
|
1884
2103
|
const addressSpace = engine.addressSpace;
|
|
2104
|
+
if (!addressSpace) {
|
|
2105
|
+
g_sendError(channel, message, node_opcua_service_subscription_1.CreateSubscriptionResponse, node_opcua_status_code_1.StatusCodes.BadSessionClosed);
|
|
2106
|
+
return;
|
|
2107
|
+
}
|
|
1885
2108
|
const request = message.request;
|
|
1886
2109
|
(0, node_opcua_assert_1.assert)(request instanceof node_opcua_service_subscription_1.CreateSubscriptionRequest);
|
|
1887
2110
|
this._apply_on_SessionObject(node_opcua_service_subscription_1.CreateSubscriptionResponse, message, channel, (session, sendResponse, sendError) => {
|
|
@@ -1910,7 +2133,7 @@ class OPCUAServer extends base_server_1.OPCUABaseServer {
|
|
|
1910
2133
|
(0, node_opcua_assert_1.assert)(request instanceof node_opcua_service_subscription_1.DeleteSubscriptionsRequest);
|
|
1911
2134
|
this._apply_on_SubscriptionIds(node_opcua_service_subscription_1.DeleteSubscriptionsResponse, message, channel, async (session, subscriptionId) => {
|
|
1912
2135
|
let subscription = this.engine.findOrphanSubscription(subscriptionId);
|
|
1913
|
-
//
|
|
2136
|
+
// c8 ignore next
|
|
1914
2137
|
if (subscription) {
|
|
1915
2138
|
warningLog("Deleting an orphan subscription", subscriptionId);
|
|
1916
2139
|
await this._beforeDeleteSubscription(subscription);
|
|
@@ -1942,9 +2165,13 @@ class OPCUAServer extends base_server_1.OPCUABaseServer {
|
|
|
1942
2165
|
_on_CreateMonitoredItemsRequest(message, channel) {
|
|
1943
2166
|
const engine = this.engine;
|
|
1944
2167
|
const addressSpace = engine.addressSpace;
|
|
2168
|
+
if (!addressSpace) {
|
|
2169
|
+
g_sendError(channel, message, node_opcua_service_subscription_1.CreateMonitoredItemsResponse, node_opcua_status_code_1.StatusCodes.BadSessionClosed);
|
|
2170
|
+
return;
|
|
2171
|
+
}
|
|
1945
2172
|
const request = message.request;
|
|
1946
2173
|
(0, node_opcua_assert_1.assert)(request instanceof node_opcua_service_subscription_1.CreateMonitoredItemsRequest);
|
|
1947
|
-
this._apply_on_Subscription(node_opcua_service_subscription_1.CreateMonitoredItemsResponse, message, channel, async (
|
|
2174
|
+
this._apply_on_Subscription(node_opcua_service_subscription_1.CreateMonitoredItemsResponse, message, channel, async (_session, subscription, sendResponse, sendError) => {
|
|
1948
2175
|
const timestampsToReturn = request.timestampsToReturn;
|
|
1949
2176
|
if (timestampsToReturn === node_opcua_service_read_1.TimestampsToReturn.Invalid) {
|
|
1950
2177
|
return sendError(node_opcua_status_code_1.StatusCodes.BadTimestampsToReturnInvalid);
|
|
@@ -1963,7 +2190,9 @@ class OPCUAServer extends base_server_1.OPCUABaseServer {
|
|
|
1963
2190
|
const resultsPromise = request.itemsToCreate.map(async (monitoredItemCreateRequest) => {
|
|
1964
2191
|
const { monitoredItem, createResult } = subscription.preCreateMonitoredItem(addressSpace, timestampsToReturn, monitoredItemCreateRequest);
|
|
1965
2192
|
if (monitoredItem) {
|
|
1966
|
-
|
|
2193
|
+
if (options.onCreateMonitoredItem) {
|
|
2194
|
+
await options.onCreateMonitoredItem(subscription, monitoredItem);
|
|
2195
|
+
}
|
|
1967
2196
|
subscription.postCreateMonitoredItem(monitoredItem, monitoredItemCreateRequest, createResult);
|
|
1968
2197
|
}
|
|
1969
2198
|
return createResult;
|
|
@@ -1990,7 +2219,7 @@ class OPCUAServer extends base_server_1.OPCUABaseServer {
|
|
|
1990
2219
|
_on_ModifySubscriptionRequest(message, channel) {
|
|
1991
2220
|
const request = message.request;
|
|
1992
2221
|
(0, node_opcua_assert_1.assert)(request instanceof node_opcua_service_subscription_1.ModifySubscriptionRequest);
|
|
1993
|
-
this._apply_on_Subscription(node_opcua_service_subscription_1.ModifySubscriptionResponse, message, channel, async (
|
|
2222
|
+
this._apply_on_Subscription(node_opcua_service_subscription_1.ModifySubscriptionResponse, message, channel, async (_session, subscription, sendResponse, _sendError) => {
|
|
1994
2223
|
subscription.modify(request);
|
|
1995
2224
|
const response = new node_opcua_service_subscription_1.ModifySubscriptionResponse({
|
|
1996
2225
|
revisedLifetimeCount: subscription.lifeTimeCount,
|
|
@@ -2003,7 +2232,7 @@ class OPCUAServer extends base_server_1.OPCUABaseServer {
|
|
|
2003
2232
|
_on_ModifyMonitoredItemsRequest(message, channel) {
|
|
2004
2233
|
const request = message.request;
|
|
2005
2234
|
(0, node_opcua_assert_1.assert)(request instanceof node_opcua_service_subscription_1.ModifyMonitoredItemsRequest);
|
|
2006
|
-
this._apply_on_Subscription(node_opcua_service_subscription_1.ModifyMonitoredItemsResponse, message, channel, async (
|
|
2235
|
+
this._apply_on_Subscription(node_opcua_service_subscription_1.ModifyMonitoredItemsResponse, message, channel, async (_session, subscription, sendResponse, sendError) => {
|
|
2007
2236
|
const timestampsToReturn = request.timestampsToReturn;
|
|
2008
2237
|
if (timestampsToReturn === node_opcua_service_read_1.TimestampsToReturn.Invalid) {
|
|
2009
2238
|
return sendError(node_opcua_status_code_1.StatusCodes.BadTimestampsToReturnInvalid);
|
|
@@ -2011,7 +2240,7 @@ class OPCUAServer extends base_server_1.OPCUABaseServer {
|
|
|
2011
2240
|
if (!request.itemsToModify || request.itemsToModify.length === 0) {
|
|
2012
2241
|
return sendError(node_opcua_status_code_1.StatusCodes.BadNothingToDo);
|
|
2013
2242
|
}
|
|
2014
|
-
/*
|
|
2243
|
+
/* c8 ignore next */
|
|
2015
2244
|
if (this.engine.serverCapabilities.operationLimits.maxMonitoredItemsPerCall > 0) {
|
|
2016
2245
|
if (request.itemsToModify.length > this.engine.serverCapabilities.operationLimits.maxMonitoredItemsPerCall) {
|
|
2017
2246
|
return sendError(node_opcua_status_code_1.StatusCodes.BadTooManyOperations);
|
|
@@ -2022,7 +2251,9 @@ class OPCUAServer extends base_server_1.OPCUABaseServer {
|
|
|
2022
2251
|
const monitoredItemId = item.monitoredItemId;
|
|
2023
2252
|
const monitoredItem = subscription.getMonitoredItem(monitoredItemId);
|
|
2024
2253
|
if (!monitoredItem) {
|
|
2025
|
-
return new node_opcua_service_subscription_1.MonitoredItemModifyResult({
|
|
2254
|
+
return new node_opcua_service_subscription_1.MonitoredItemModifyResult({
|
|
2255
|
+
statusCode: node_opcua_status_code_1.StatusCodes.BadMonitoredItemIdInvalid
|
|
2256
|
+
});
|
|
2026
2257
|
}
|
|
2027
2258
|
// adjust samplingInterval if === -1
|
|
2028
2259
|
if (item.requestedParameters.samplingInterval === -1) {
|
|
@@ -2040,7 +2271,7 @@ class OPCUAServer extends base_server_1.OPCUABaseServer {
|
|
|
2040
2271
|
_on_PublishRequest(message, channel) {
|
|
2041
2272
|
const request = message.request;
|
|
2042
2273
|
(0, node_opcua_assert_1.assert)(request instanceof node_opcua_service_subscription_1.PublishRequest);
|
|
2043
|
-
this._apply_on_SessionObject(node_opcua_service_subscription_1.PublishResponse, message, channel, (session, sendResponse,
|
|
2274
|
+
this._apply_on_SessionObject(node_opcua_service_subscription_1.PublishResponse, message, channel, (session, sendResponse, _sendError) => {
|
|
2044
2275
|
(0, node_opcua_assert_1.assert)(session);
|
|
2045
2276
|
(0, node_opcua_assert_1.assert)(session.publishEngine); // server.publishEngine doesn't exists, OPCUAServer has probably shut down already
|
|
2046
2277
|
session.publishEngine._on_PublishRequest(request, (_request1, response) => {
|
|
@@ -2052,19 +2283,19 @@ class OPCUAServer extends base_server_1.OPCUABaseServer {
|
|
|
2052
2283
|
const request = message.request;
|
|
2053
2284
|
(0, node_opcua_assert_1.assert)(request instanceof node_opcua_service_subscription_1.SetPublishingModeRequest);
|
|
2054
2285
|
const publishingEnabled = request.publishingEnabled;
|
|
2055
|
-
this._apply_on_Subscriptions(node_opcua_service_subscription_1.SetPublishingModeResponse, message, channel, async (
|
|
2286
|
+
this._apply_on_Subscriptions(node_opcua_service_subscription_1.SetPublishingModeResponse, message, channel, async (_session, subscription) => {
|
|
2056
2287
|
return subscription.setPublishingMode(publishingEnabled);
|
|
2057
2288
|
});
|
|
2058
2289
|
}
|
|
2059
2290
|
_on_DeleteMonitoredItemsRequest(message, channel) {
|
|
2060
2291
|
const request = message.request;
|
|
2061
2292
|
(0, node_opcua_assert_1.assert)(request instanceof node_opcua_service_subscription_1.DeleteMonitoredItemsRequest);
|
|
2062
|
-
this._apply_on_Subscription(node_opcua_service_subscription_1.DeleteMonitoredItemsResponse, message, channel, async (
|
|
2063
|
-
/*
|
|
2293
|
+
this._apply_on_Subscription(node_opcua_service_subscription_1.DeleteMonitoredItemsResponse, message, channel, async (_session, subscription, sendResponse, sendError) => {
|
|
2294
|
+
/* c8 ignore next */
|
|
2064
2295
|
if (!request.monitoredItemIds || request.monitoredItemIds.length === 0) {
|
|
2065
2296
|
return sendError(node_opcua_status_code_1.StatusCodes.BadNothingToDo);
|
|
2066
2297
|
}
|
|
2067
|
-
/*
|
|
2298
|
+
/* c8 ignore next */
|
|
2068
2299
|
if (this.engine.serverCapabilities.operationLimits.maxMonitoredItemsPerCall > 0) {
|
|
2069
2300
|
if (request.monitoredItemIds.length > this.engine.serverCapabilities.operationLimits.maxMonitoredItemsPerCall) {
|
|
2070
2301
|
return sendError(node_opcua_status_code_1.StatusCodes.BadTooManyOperations);
|
|
@@ -2096,7 +2327,7 @@ class OPCUAServer extends base_server_1.OPCUABaseServer {
|
|
|
2096
2327
|
_on_SetTriggeringRequest(message, channel) {
|
|
2097
2328
|
const request = message.request;
|
|
2098
2329
|
(0, node_opcua_assert_1.assert)(request instanceof node_opcua_service_subscription_1.SetTriggeringRequest);
|
|
2099
|
-
this._apply_on_Subscription(node_opcua_service_subscription_1.SetTriggeringResponse, message, channel, async (
|
|
2330
|
+
this._apply_on_Subscription(node_opcua_service_subscription_1.SetTriggeringResponse, message, channel, async (_session, subscription, sendResponse, sendError) => {
|
|
2100
2331
|
/* */
|
|
2101
2332
|
const { triggeringItemId, linksToAdd, linksToRemove } = request;
|
|
2102
2333
|
/**
|
|
@@ -2114,7 +2345,9 @@ class OPCUAServer extends base_server_1.OPCUABaseServer {
|
|
|
2114
2345
|
}
|
|
2115
2346
|
const { addResults, removeResults, statusCode } = subscription.setTriggering(triggeringItemId, linksToAdd, linksToRemove);
|
|
2116
2347
|
if (statusCode.isNotGood()) {
|
|
2117
|
-
const response = new node_opcua_types_1.ServiceFault({
|
|
2348
|
+
const response = new node_opcua_types_1.ServiceFault({
|
|
2349
|
+
responseHeader: { serviceResult: statusCode }
|
|
2350
|
+
});
|
|
2118
2351
|
sendResponse(response);
|
|
2119
2352
|
}
|
|
2120
2353
|
else {
|
|
@@ -2133,12 +2366,16 @@ class OPCUAServer extends base_server_1.OPCUABaseServer {
|
|
|
2133
2366
|
if (!this.options.onDeleteMonitoredItem) {
|
|
2134
2367
|
return;
|
|
2135
2368
|
}
|
|
2136
|
-
|
|
2369
|
+
const t = this.options.onDeleteMonitoredItem.bind(null, subscription);
|
|
2370
|
+
const functor = async (monitoredItem) => {
|
|
2371
|
+
await t(monitoredItem);
|
|
2372
|
+
};
|
|
2373
|
+
await subscription.applyOnMonitoredItem(functor);
|
|
2137
2374
|
}
|
|
2138
2375
|
_on_RepublishRequest(message, channel) {
|
|
2139
2376
|
const request = message.request;
|
|
2140
2377
|
(0, node_opcua_assert_1.assert)(request instanceof node_opcua_service_subscription_1.RepublishRequest);
|
|
2141
|
-
this._apply_on_Subscription(node_opcua_service_subscription_1.RepublishResponse, message, channel, async (
|
|
2378
|
+
this._apply_on_Subscription(node_opcua_service_subscription_1.RepublishResponse, message, channel, async (_session, subscription, sendResponse, sendError) => {
|
|
2142
2379
|
// update diagnostic counter
|
|
2143
2380
|
subscription.subscriptionDiagnostics.republishRequestCount += 1;
|
|
2144
2381
|
subscription.subscriptionDiagnostics.republishMessageRequestCount += 1;
|
|
@@ -2165,12 +2402,12 @@ class OPCUAServer extends base_server_1.OPCUABaseServer {
|
|
|
2165
2402
|
_on_SetMonitoringModeRequest(message, channel) {
|
|
2166
2403
|
const request = message.request;
|
|
2167
2404
|
(0, node_opcua_assert_1.assert)(request instanceof node_opcua_service_subscription_1.SetMonitoringModeRequest);
|
|
2168
|
-
this._apply_on_Subscription(node_opcua_service_subscription_1.SetMonitoringModeResponse, message, channel, async (
|
|
2169
|
-
/*
|
|
2405
|
+
this._apply_on_Subscription(node_opcua_service_subscription_1.SetMonitoringModeResponse, message, channel, async (_session, subscription, sendResponse, sendError) => {
|
|
2406
|
+
/* c8 ignore next */
|
|
2170
2407
|
if (!request.monitoredItemIds || request.monitoredItemIds.length === 0) {
|
|
2171
2408
|
return sendError(node_opcua_status_code_1.StatusCodes.BadNothingToDo);
|
|
2172
2409
|
}
|
|
2173
|
-
/*
|
|
2410
|
+
/* c8 ignore next */
|
|
2174
2411
|
if (this.engine.serverCapabilities.operationLimits.maxMonitoredItemsPerCall > 0) {
|
|
2175
2412
|
if (request.monitoredItemIds.length > this.engine.serverCapabilities.operationLimits.maxMonitoredItemsPerCall) {
|
|
2176
2413
|
return sendError(node_opcua_status_code_1.StatusCodes.BadTooManyOperations);
|
|
@@ -2198,7 +2435,7 @@ class OPCUAServer extends base_server_1.OPCUABaseServer {
|
|
|
2198
2435
|
_on_TranslateBrowsePathsToNodeIdsRequest(message, channel) {
|
|
2199
2436
|
const request = message.request;
|
|
2200
2437
|
(0, node_opcua_assert_1.assert)(request instanceof node_opcua_service_translate_browse_path_1.TranslateBrowsePathsToNodeIdsRequest);
|
|
2201
|
-
this._apply_on_SessionObject(node_opcua_service_translate_browse_path_1.TranslateBrowsePathsToNodeIdsResponse, message, channel, async (
|
|
2438
|
+
this._apply_on_SessionObject(node_opcua_service_translate_browse_path_1.TranslateBrowsePathsToNodeIdsResponse, message, channel, async (_session, sendResponse, sendError) => {
|
|
2202
2439
|
if (!request.browsePaths || request.browsePaths.length === 0) {
|
|
2203
2440
|
return sendError(node_opcua_status_code_1.StatusCodes.BadNothingToDo);
|
|
2204
2441
|
}
|
|
@@ -2217,7 +2454,7 @@ class OPCUAServer extends base_server_1.OPCUABaseServer {
|
|
|
2217
2454
|
});
|
|
2218
2455
|
sendResponse(response);
|
|
2219
2456
|
})
|
|
2220
|
-
.catch((
|
|
2457
|
+
.catch((_err) => {
|
|
2221
2458
|
sendError(node_opcua_status_code_1.StatusCodes.BadInternalError);
|
|
2222
2459
|
});
|
|
2223
2460
|
});
|
|
@@ -2231,7 +2468,6 @@ class OPCUAServer extends base_server_1.OPCUABaseServer {
|
|
|
2231
2468
|
const request = message.request;
|
|
2232
2469
|
(0, node_opcua_assert_1.assert)(request instanceof node_opcua_service_call_1.CallRequest);
|
|
2233
2470
|
this._apply_on_SessionObject(node_opcua_service_call_1.CallResponse, message, channel, (session, sendResponse, sendError) => {
|
|
2234
|
-
let response;
|
|
2235
2471
|
if (!request.methodsToCall || request.methodsToCall.length === 0) {
|
|
2236
2472
|
return sendError(node_opcua_status_code_1.StatusCodes.BadNothingToDo);
|
|
2237
2473
|
}
|
|
@@ -2250,7 +2486,7 @@ class OPCUAServer extends base_server_1.OPCUABaseServer {
|
|
|
2250
2486
|
filterDiagnosticInfo(request.requestHeader.returnDiagnostics, response);
|
|
2251
2487
|
sendResponse(response);
|
|
2252
2488
|
})
|
|
2253
|
-
.catch((
|
|
2489
|
+
.catch((_err) => {
|
|
2254
2490
|
sendError(node_opcua_status_code_1.StatusCodes.BadInternalError);
|
|
2255
2491
|
});
|
|
2256
2492
|
});
|
|
@@ -2299,42 +2535,42 @@ class OPCUAServer extends base_server_1.OPCUABaseServer {
|
|
|
2299
2535
|
sendResponse(response);
|
|
2300
2536
|
});
|
|
2301
2537
|
}
|
|
2302
|
-
/*
|
|
2538
|
+
/* c8 ignore next */
|
|
2303
2539
|
_on_Cancel(message, channel) {
|
|
2304
|
-
|
|
2540
|
+
g_sendError(channel, message, node_opcua_types_1.CancelResponse, node_opcua_status_code_1.StatusCodes.BadServiceUnsupported);
|
|
2305
2541
|
}
|
|
2306
2542
|
// NodeManagement Service Set Overview
|
|
2307
2543
|
// This Service Set defines Services to add and delete AddressSpace Nodes and References between them. All added
|
|
2308
2544
|
// Nodes continue to exist in the AddressSpace even if the Client that created them disconnects from the Server.
|
|
2309
2545
|
//
|
|
2310
|
-
/*
|
|
2546
|
+
/* c8 ignore next */
|
|
2311
2547
|
_on_AddNodes(message, channel) {
|
|
2312
|
-
|
|
2548
|
+
g_sendError(channel, message, node_opcua_service_node_management_1.AddNodesResponse, node_opcua_status_code_1.StatusCodes.BadServiceUnsupported);
|
|
2313
2549
|
}
|
|
2314
|
-
/*
|
|
2550
|
+
/* c8 ignore next */
|
|
2315
2551
|
_on_AddReferences(message, channel) {
|
|
2316
|
-
|
|
2552
|
+
g_sendError(channel, message, node_opcua_service_node_management_1.AddReferencesResponse, node_opcua_status_code_1.StatusCodes.BadServiceUnsupported);
|
|
2317
2553
|
}
|
|
2318
|
-
/*
|
|
2554
|
+
/* c8 ignore next */
|
|
2319
2555
|
_on_DeleteNodes(message, channel) {
|
|
2320
|
-
|
|
2556
|
+
g_sendError(channel, message, node_opcua_service_node_management_1.DeleteNodesResponse, node_opcua_status_code_1.StatusCodes.BadServiceUnsupported);
|
|
2321
2557
|
}
|
|
2322
|
-
/*
|
|
2558
|
+
/* c8 ignore next */
|
|
2323
2559
|
_on_DeleteReferences(message, channel) {
|
|
2324
|
-
|
|
2560
|
+
g_sendError(channel, message, node_opcua_service_node_management_1.DeleteReferencesResponse, node_opcua_status_code_1.StatusCodes.BadServiceUnsupported);
|
|
2325
2561
|
}
|
|
2326
2562
|
// Query Service
|
|
2327
|
-
/*
|
|
2563
|
+
/* c8 ignore next */
|
|
2328
2564
|
_on_QueryFirst(message, channel) {
|
|
2329
|
-
|
|
2565
|
+
g_sendError(channel, message, node_opcua_service_query_1.QueryFirstResponse, node_opcua_status_code_1.StatusCodes.BadServiceUnsupported);
|
|
2330
2566
|
}
|
|
2331
|
-
/*
|
|
2567
|
+
/* c8 ignore next */
|
|
2332
2568
|
_on_QueryNext(message, channel) {
|
|
2333
|
-
|
|
2569
|
+
g_sendError(channel, message, node_opcua_service_query_1.QueryNextResponse, node_opcua_status_code_1.StatusCodes.BadServiceUnsupported);
|
|
2334
2570
|
}
|
|
2335
|
-
/*
|
|
2571
|
+
/* c8 ignore next */
|
|
2336
2572
|
_on_HistoryUpdate(message, channel) {
|
|
2337
|
-
|
|
2573
|
+
g_sendError(channel, message, node_opcua_service_history_1.HistoryUpdateResponse, node_opcua_status_code_1.StatusCodes.BadServiceUnsupported);
|
|
2338
2574
|
}
|
|
2339
2575
|
createEndpoint(port1, serverOptions) {
|
|
2340
2576
|
// add the tcp/ip endpoint with no security
|
|
@@ -2354,23 +2590,23 @@ class OPCUAServer extends base_server_1.OPCUABaseServer {
|
|
|
2354
2590
|
return endPoint;
|
|
2355
2591
|
}
|
|
2356
2592
|
createEndpointDescriptions(serverOption, endpointOptions) {
|
|
2357
|
-
/*
|
|
2593
|
+
/* c8 ignore next */
|
|
2358
2594
|
if (!endpointOptions) {
|
|
2359
2595
|
throw new Error("internal error");
|
|
2360
2596
|
}
|
|
2361
2597
|
const hostname = (0, node_opcua_hostname_1.getFullyQualifiedDomainName)();
|
|
2362
2598
|
endpointOptions.hostname = endpointOptions.hostname || hostname;
|
|
2363
2599
|
endpointOptions.port = endpointOptions.port === undefined ? 26543 : endpointOptions.port;
|
|
2364
|
-
/*
|
|
2365
|
-
if (!Object.
|
|
2366
|
-
!isFinite(endpointOptions.port) ||
|
|
2600
|
+
/* c8 ignore next */
|
|
2601
|
+
if (!Object.hasOwn(endpointOptions, "port") ||
|
|
2602
|
+
!Number.isFinite(endpointOptions.port) ||
|
|
2367
2603
|
typeof endpointOptions.port !== "number") {
|
|
2368
2604
|
throw new Error("expecting a valid port (number) when specified. alternatively you can specify port:0 and node-opcua will choose the first available port");
|
|
2369
2605
|
}
|
|
2370
2606
|
const port = Number(endpointOptions.port || 0);
|
|
2371
2607
|
const endPoint = this.createEndpoint(port, serverOption);
|
|
2372
2608
|
endpointOptions.alternateHostname = endpointOptions.alternateHostname || [];
|
|
2373
|
-
const alternateHostname = endpointOptions.alternateHostname
|
|
2609
|
+
const alternateHostname = Array.isArray(endpointOptions.alternateHostname)
|
|
2374
2610
|
? endpointOptions.alternateHostname
|
|
2375
2611
|
: [endpointOptions.alternateHostname];
|
|
2376
2612
|
const allowAnonymous = endpointOptions.allowAnonymous === undefined ? true : !!endpointOptions.allowAnonymous;
|
|
@@ -2382,7 +2618,8 @@ class OPCUAServer extends base_server_1.OPCUABaseServer {
|
|
|
2382
2618
|
alternateHostname,
|
|
2383
2619
|
disableDiscovery: !!endpointOptions.disableDiscovery,
|
|
2384
2620
|
// xx hostname,
|
|
2385
|
-
resourcePath: serverOption.resourcePath || ""
|
|
2621
|
+
resourcePath: serverOption.resourcePath || "",
|
|
2622
|
+
advertisedEndpoints: endpointOptions.advertisedEndpoints,
|
|
2386
2623
|
// TODO userTokenTypes: endpointOptions.userTokenTypes || undefined,
|
|
2387
2624
|
// TODO allowUnsecurePassword: endpointOptions.allowUnsecurePassword || false
|
|
2388
2625
|
});
|
|
@@ -2392,6 +2629,10 @@ class OPCUAServer extends base_server_1.OPCUABaseServer {
|
|
|
2392
2629
|
await super.initializeCM();
|
|
2393
2630
|
await this.userCertificateManager.initialize();
|
|
2394
2631
|
}
|
|
2632
|
+
// biome-ignore lint/suspicious/noExplicitAny: must match EventEmitter.on() signature
|
|
2633
|
+
on(event, eventHandler) {
|
|
2634
|
+
return super.on(event, eventHandler);
|
|
2635
|
+
}
|
|
2395
2636
|
}
|
|
2396
2637
|
exports.OPCUAServer = OPCUAServer;
|
|
2397
2638
|
const userIdentityTokenPasswordRemoved = (userIdentityToken) => {
|
|
@@ -2426,7 +2667,7 @@ function raiseAuditActivateSessionEventType(session) {
|
|
|
2426
2667
|
sessionId: { dataType: "NodeId", value: session.nodeId },
|
|
2427
2668
|
/* part 5 - 6.4.10 AuditActivateSessionEventType */
|
|
2428
2669
|
clientSoftwareCertificates: {
|
|
2429
|
-
arrayType:
|
|
2670
|
+
arrayType: node_opcua_variant_1.VariantArrayType.Array,
|
|
2430
2671
|
dataType: "ExtensionObject" /* SignedSoftwareCertificate */,
|
|
2431
2672
|
value: []
|
|
2432
2673
|
},
|
|
@@ -2441,12 +2682,14 @@ function raiseAuditActivateSessionEventType(session) {
|
|
|
2441
2682
|
// use the same identifier in all AuditEvents related to the Session Service Set
|
|
2442
2683
|
// (AuditCreateSessionEventType, AuditActivateSessionEventType and their subtypes) and
|
|
2443
2684
|
// the SecureChannel Service Set (AuditChannelEventType and its subtypes).
|
|
2444
|
-
secureChannelId: {
|
|
2685
|
+
secureChannelId: {
|
|
2686
|
+
dataType: "String",
|
|
2687
|
+
value: session.channel?.channelId?.toString() ?? ""
|
|
2688
|
+
}
|
|
2445
2689
|
});
|
|
2446
2690
|
}
|
|
2447
2691
|
}
|
|
2448
2692
|
const opts = { multiArgs: false };
|
|
2449
|
-
OPCUAServer.prototype.start = (0, thenify_ex_1.withCallback)(OPCUAServer.prototype.start, opts);
|
|
2450
2693
|
OPCUAServer.prototype.initialize = (0, thenify_ex_1.withCallback)(OPCUAServer.prototype.initialize, opts);
|
|
2451
2694
|
OPCUAServer.prototype.shutdown = (0, thenify_ex_1.withCallback)(OPCUAServer.prototype.shutdown, opts);
|
|
2452
2695
|
//# sourceMappingURL=opcua_server.js.map
|