node-opcua-server 2.53.0 → 2.56.1
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/LICENSE +20 -20
- package/dist/base_server.js +12 -14
- package/dist/base_server.js.map +1 -1
- package/dist/factory.d.ts +4 -2
- package/dist/factory.js.map +1 -1
- package/dist/history_server_capabilities.js.map +1 -1
- package/dist/i_server_side_publish_engine.d.ts +1 -1
- package/dist/i_server_side_publish_engine.js +1 -1
- package/dist/i_server_side_publish_engine.js.map +1 -1
- package/dist/monitored_item.d.ts +3 -0
- package/dist/monitored_item.js +7 -14
- 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 +29 -44
- package/dist/opcua_server.js +218 -262
- package/dist/opcua_server.js.map +1 -1
- package/dist/queue.js +1 -0
- package/dist/queue.js.map +1 -1
- package/dist/register_server_manager.d.ts +4 -1
- package/dist/register_server_manager.js +5 -5
- package/dist/register_server_manager.js.map +1 -1
- package/dist/register_server_manager_hidden.d.ts +1 -1
- package/dist/register_server_manager_hidden.js.map +1 -1
- package/dist/register_server_manager_mdns_only.d.ts +4 -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_capabilities.js.map +1 -1
- package/dist/server_end_point.d.ts +4 -1
- package/dist/server_end_point.js +10 -11
- package/dist/server_end_point.js.map +1 -1
- package/dist/server_engine.d.ts +11 -7
- package/dist/server_engine.js +72 -74
- package/dist/server_engine.js.map +1 -1
- package/dist/server_publish_engine.d.ts +4 -1
- package/dist/server_publish_engine.js +5 -5
- package/dist/server_publish_engine.js.map +1 -1
- package/dist/server_publish_engine_for_orphan_subscriptions.d.ts +2 -2
- package/dist/server_publish_engine_for_orphan_subscriptions.js.map +1 -1
- package/dist/server_session.d.ts +1 -1
- package/dist/server_session.js +24 -29
- package/dist/server_session.js.map +1 -1
- package/dist/server_subscription.d.ts +3 -1
- package/dist/server_subscription.js +6 -6
- package/dist/server_subscription.js.map +1 -1
- package/dist/sessions_compatible_for_transfer.js +2 -1
- package/dist/sessions_compatible_for_transfer.js.map +1 -1
- package/dist/validate_filter.js +4 -7
- package/dist/validate_filter.js.map +1 -1
- package/package.json +45 -44
- package/source/base_server.ts +19 -22
- package/source/factory.ts +5 -2
- package/source/history_server_capabilities.ts +3 -4
- package/source/i_channel_data.ts +4 -8
- package/source/i_register_server_manager.ts +0 -3
- package/source/i_server_side_publish_engine.ts +5 -6
- package/source/i_socket_data.ts +1 -1
- package/source/index.ts +14 -14
- package/source/monitored_item.ts +32 -44
- package/source/node_sampler.ts +82 -82
- package/source/opcua_server.ts +326 -357
- package/source/queue.ts +6 -7
- package/source/register_server_manager.ts +35 -23
- package/source/register_server_manager_hidden.ts +8 -10
- package/source/register_server_manager_mdns_only.ts +8 -13
- package/source/server_capabilities.ts +0 -5
- package/source/server_end_point.ts +28 -30
- package/source/server_engine.ts +122 -122
- package/source/server_publish_engine.ts +24 -21
- package/source/server_publish_engine_for_orphan_subscriptions.ts +26 -26
- package/source/server_session.ts +44 -49
- package/source/server_subscription.ts +23 -23
- package/source/sessions_compatible_for_transfer.ts +26 -25
- package/source/validate_filter.ts +8 -22
- package/test_helpers/create_certificates.js +1 -1
package/dist/opcua_server.js
CHANGED
|
@@ -61,6 +61,8 @@ function isSubscriptionIdInvalid(subscriptionId) {
|
|
|
61
61
|
return subscriptionId < 0 || subscriptionId >= 0xffffffff;
|
|
62
62
|
}
|
|
63
63
|
// tslint:disable-next-line:no-var-requires
|
|
64
|
+
const thenify = require("thenify");
|
|
65
|
+
// tslint:disable-next-line:no-var-requires
|
|
64
66
|
const package_info = require("../package.json");
|
|
65
67
|
const debugLog = (0, node_opcua_debug_1.make_debugLog)(__filename);
|
|
66
68
|
const errorLog = (0, node_opcua_debug_1.make_errorLog)(__filename);
|
|
@@ -93,7 +95,7 @@ function _adjust_session_timeout(sessionTimeout) {
|
|
|
93
95
|
}
|
|
94
96
|
function channel_has_session(channel, session) {
|
|
95
97
|
if (session.channel === channel) {
|
|
96
|
-
(0, node_opcua_assert_1.assert)(
|
|
98
|
+
(0, node_opcua_assert_1.assert)(Object.prototype.hasOwnProperty.call(channel.sessionTokens, session.authenticationToken.toString()));
|
|
97
99
|
return true;
|
|
98
100
|
}
|
|
99
101
|
return false;
|
|
@@ -304,8 +306,7 @@ function build_scanning_node_function(context, addressSpace, monitoredItem, item
|
|
|
304
306
|
// causes a Notification to be generated.
|
|
305
307
|
// only record value when it has changed
|
|
306
308
|
return function func(oldDataValue, callback) {
|
|
307
|
-
|
|
308
|
-
(0, node_opcua_assert_1.assert)(self instanceof monitored_item_1.MonitoredItem);
|
|
309
|
+
(0, node_opcua_assert_1.assert)(this instanceof monitored_item_1.MonitoredItem);
|
|
309
310
|
(0, node_opcua_assert_1.assert)(oldDataValue instanceof node_opcua_data_value_1.DataValue);
|
|
310
311
|
(0, node_opcua_assert_1.assert)(typeof callback === "function");
|
|
311
312
|
const newDataValue = node.readAttribute(null, itemToMonitor.attributeId);
|
|
@@ -387,6 +388,70 @@ function _installRegisterServerManager(self) {
|
|
|
387
388
|
self.emit("serverUnregistered");
|
|
388
389
|
});
|
|
389
390
|
}
|
|
391
|
+
function validate_applicationUri(channel, request) {
|
|
392
|
+
const applicationUri = request.clientDescription.applicationUri;
|
|
393
|
+
const clientCertificate = request.clientCertificate;
|
|
394
|
+
// if session is insecure there is no need to check certificate information
|
|
395
|
+
if (channel.securityMode === node_opcua_secure_channel_1.MessageSecurityMode.None) {
|
|
396
|
+
return true; // assume correct
|
|
397
|
+
}
|
|
398
|
+
if (!clientCertificate || clientCertificate.length === 0) {
|
|
399
|
+
return true; // can't check
|
|
400
|
+
}
|
|
401
|
+
const e = (0, node_opcua_crypto_1.exploreCertificate)(clientCertificate);
|
|
402
|
+
const applicationUriFromCert = e.tbsCertificate.extensions.subjectAltName.uniformResourceIdentifier[0];
|
|
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
|
+
}
|
|
390
455
|
var RegisterServerMethod;
|
|
391
456
|
(function (RegisterServerMethod) {
|
|
392
457
|
RegisterServerMethod[RegisterServerMethod["HIDDEN"] = 1] = "HIDDEN";
|
|
@@ -404,6 +469,7 @@ class OPCUAServer extends base_server_1.OPCUABaseServer {
|
|
|
404
469
|
* false if anonymous connection are not allowed
|
|
405
470
|
*/
|
|
406
471
|
this.allowAnonymous = false;
|
|
472
|
+
this.allowAnonymous = false;
|
|
407
473
|
options = options || {};
|
|
408
474
|
this.options = options;
|
|
409
475
|
/**
|
|
@@ -522,8 +588,7 @@ class OPCUAServer extends base_server_1.OPCUABaseServer {
|
|
|
522
588
|
*/
|
|
523
589
|
get currentChannelCount() {
|
|
524
590
|
// TODO : move to base
|
|
525
|
-
|
|
526
|
-
return self.endpoints.reduce((currentValue, endPoint) => {
|
|
591
|
+
return this.endpoints.reduce((currentValue, endPoint) => {
|
|
527
592
|
return currentValue + endPoint.currentChannelCount;
|
|
528
593
|
}, 0);
|
|
529
594
|
}
|
|
@@ -692,13 +757,15 @@ class OPCUAServer extends base_server_1.OPCUABaseServer {
|
|
|
692
757
|
let eventTypeNode = eventType;
|
|
693
758
|
if (typeof eventType === "string") {
|
|
694
759
|
eventTypeNode = this.engine.addressSpace.findEventType(eventType);
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
760
|
+
if (eventTypeNode) {
|
|
761
|
+
return server.raiseEvent(eventTypeNode, options);
|
|
762
|
+
}
|
|
763
|
+
else {
|
|
764
|
+
console.warn(" cannot find event type ", eventType);
|
|
765
|
+
}
|
|
699
766
|
}
|
|
700
767
|
else {
|
|
701
|
-
|
|
768
|
+
return server.raiseEvent(eventTypeNode, options);
|
|
702
769
|
}
|
|
703
770
|
}
|
|
704
771
|
/**
|
|
@@ -906,7 +973,10 @@ class OPCUAServer extends base_server_1.OPCUABaseServer {
|
|
|
906
973
|
(0, node_opcua_assert_1.assert)(typeof callback === "function");
|
|
907
974
|
const userTokenType = getTokenType(userIdentityToken);
|
|
908
975
|
const userTokenPolicy = findUserTokenByPolicy(session.getEndpointDescription(), userTokenType, userIdentityToken.policyId);
|
|
909
|
-
|
|
976
|
+
/** istanbul ignore next */
|
|
977
|
+
if (!userTokenPolicy) {
|
|
978
|
+
return callback(null, false);
|
|
979
|
+
}
|
|
910
980
|
// find if a userToken exists
|
|
911
981
|
if (userIdentityToken instanceof node_opcua_service_session_1.UserNameIdentityToken) {
|
|
912
982
|
return this.userNameIdentityTokenAuthenticateUser(channel, session, userTokenPolicy, userIdentityToken, callback);
|
|
@@ -917,12 +987,12 @@ class OPCUAServer extends base_server_1.OPCUABaseServer {
|
|
|
917
987
|
return crypto.randomBytes(32);
|
|
918
988
|
}
|
|
919
989
|
// session services
|
|
990
|
+
// eslint-disable-next-line max-statements
|
|
920
991
|
_on_CreateSessionRequest(message, channel) {
|
|
921
992
|
return __awaiter(this, void 0, void 0, function* () {
|
|
922
|
-
const server = this;
|
|
923
993
|
const request = message.request;
|
|
924
994
|
(0, node_opcua_assert_1.assert)(request instanceof node_opcua_service_session_1.CreateSessionRequest);
|
|
925
|
-
function rejectConnection(statusCode) {
|
|
995
|
+
function rejectConnection(server, statusCode) {
|
|
926
996
|
server.engine.incrementSecurityRejectedSessionCount();
|
|
927
997
|
const response1 = new node_opcua_service_session_1.CreateSessionResponse({
|
|
928
998
|
responseHeader: { serviceResult: statusCode }
|
|
@@ -934,12 +1004,12 @@ class OPCUAServer extends base_server_1.OPCUABaseServer {
|
|
|
934
1004
|
// A Server application should limit the number of Sessions. To protect against misbehaving Clients and denial
|
|
935
1005
|
// of service attacks, the Server shall close the oldest Session that is not activated before reaching the
|
|
936
1006
|
// maximum number of supported Sessions
|
|
937
|
-
if (
|
|
938
|
-
yield _attempt_to_close_some_old_unactivated_session(
|
|
1007
|
+
if (this.currentSessionCount >= this.maxAllowedSessionNumber) {
|
|
1008
|
+
yield _attempt_to_close_some_old_unactivated_session(this);
|
|
939
1009
|
}
|
|
940
1010
|
// check if session count hasn't reach the maximum allowed sessions
|
|
941
|
-
if (
|
|
942
|
-
return rejectConnection(node_opcua_status_code_1.StatusCodes.BadTooManySessions);
|
|
1011
|
+
if (this.currentSessionCount >= this.maxAllowedSessionNumber) {
|
|
1012
|
+
return rejectConnection(this, node_opcua_status_code_1.StatusCodes.BadTooManySessions);
|
|
943
1013
|
}
|
|
944
1014
|
// Release 1.03 OPC Unified Architecture, Part 4 page 24 - CreateSession Parameters
|
|
945
1015
|
// client should prove a sessionName
|
|
@@ -964,86 +1034,24 @@ class OPCUAServer extends base_server_1.OPCUABaseServer {
|
|
|
964
1034
|
if (!request.clientNonce || request.clientNonce.length < 32) {
|
|
965
1035
|
if (channel.securityMode !== node_opcua_secure_channel_1.MessageSecurityMode.None) {
|
|
966
1036
|
errorLog(chalk.red("SERVER with secure connection: Missing or invalid client Nonce "), request.clientNonce && request.clientNonce.toString("hex"));
|
|
967
|
-
return rejectConnection(node_opcua_status_code_1.StatusCodes.BadNonceInvalid);
|
|
1037
|
+
return rejectConnection(this, node_opcua_status_code_1.StatusCodes.BadNonceInvalid);
|
|
968
1038
|
}
|
|
969
1039
|
}
|
|
970
1040
|
if ((0, node_opcua_secure_channel_1.nonceAlreadyBeenUsed)(request.clientNonce)) {
|
|
971
1041
|
errorLog(chalk.red("SERVER with secure connection: None has already been used"), request.clientNonce && request.clientNonce.toString("hex"));
|
|
972
|
-
return rejectConnection(node_opcua_status_code_1.StatusCodes.BadNonceInvalid);
|
|
973
|
-
}
|
|
974
|
-
function validate_applicationUri(applicationUri, clientCertificate) {
|
|
975
|
-
// if session is insecure there is no need to check certificate information
|
|
976
|
-
if (channel.securityMode === node_opcua_secure_channel_1.MessageSecurityMode.None) {
|
|
977
|
-
return true; // assume correct
|
|
978
|
-
}
|
|
979
|
-
if (!clientCertificate || clientCertificate.length === 0) {
|
|
980
|
-
return true; // can't check
|
|
981
|
-
}
|
|
982
|
-
const e = (0, node_opcua_crypto_1.exploreCertificate)(clientCertificate);
|
|
983
|
-
const applicationUriFromCert = e.tbsCertificate.extensions.subjectAltName.uniformResourceIdentifier[0];
|
|
984
|
-
/* istanbul ignore next */
|
|
985
|
-
if (applicationUriFromCert !== applicationUri) {
|
|
986
|
-
errorLog("BadCertificateUriInvalid!");
|
|
987
|
-
errorLog("applicationUri = ", applicationUri);
|
|
988
|
-
errorLog("applicationUriFromCert = ", applicationUriFromCert);
|
|
989
|
-
}
|
|
990
|
-
return applicationUriFromCert === applicationUri;
|
|
1042
|
+
return rejectConnection(this, node_opcua_status_code_1.StatusCodes.BadNonceInvalid);
|
|
991
1043
|
}
|
|
992
1044
|
// check application spoofing
|
|
993
1045
|
// check if applicationUri in createSessionRequest matches applicationUri in client Certificate
|
|
994
|
-
if (!validate_applicationUri(
|
|
995
|
-
return rejectConnection(node_opcua_status_code_1.StatusCodes.BadCertificateUriInvalid);
|
|
996
|
-
}
|
|
997
|
-
function validate_security_endpoint(channel1) {
|
|
998
|
-
debugLog("validate_security_endpoint = ", request.endpointUrl);
|
|
999
|
-
let endpoints = server._get_endpoints(request.endpointUrl);
|
|
1000
|
-
// endpointUrl String The network address that the Client used to access the Session Endpoint.
|
|
1001
|
-
// The HostName portion of the URL should be one of the HostNames for the application that are
|
|
1002
|
-
// specified in the Server’s ApplicationInstanceCertificate (see 7.2). The Server shall raise an
|
|
1003
|
-
// AuditUrlMismatchEventType event if the URL does not match the Server’s HostNames.
|
|
1004
|
-
// AuditUrlMismatchEventType event type is defined in Part 5.
|
|
1005
|
-
// The Server uses this information for diagnostics and to determine the set of
|
|
1006
|
-
// EndpointDescriptions to return in the response.
|
|
1007
|
-
// ToDo: check endpointUrl validity and emit an AuditUrlMismatchEventType event if not
|
|
1008
|
-
if (endpoints.length === 0) {
|
|
1009
|
-
// we have a UrlMismatch here
|
|
1010
|
-
const ua_server = server.engine.addressSpace.rootFolder.objects.server;
|
|
1011
|
-
ua_server.raiseEvent("AuditUrlMismatchEventType", {
|
|
1012
|
-
endpointUrl: { dataType: node_opcua_variant_1.DataType.String, value: request.endpointUrl }
|
|
1013
|
-
});
|
|
1014
|
-
debugLog("Cannot find endpoint in available endpoints with endpointUri", request.endpointUrl);
|
|
1015
|
-
if (OPCUAServer.requestExactEndpointUrl) {
|
|
1016
|
-
return { errCode: node_opcua_status_code_1.StatusCodes.BadServiceUnsupported };
|
|
1017
|
-
}
|
|
1018
|
-
else {
|
|
1019
|
-
endpoints = server._get_endpoints(null);
|
|
1020
|
-
}
|
|
1021
|
-
}
|
|
1022
|
-
// ignore restricted endpoints
|
|
1023
|
-
endpoints = endpoints.filter((e) => !e.restricted);
|
|
1024
|
-
const endpoints_matching_security_mode = endpoints.filter((e) => {
|
|
1025
|
-
return e.securityMode === channel1.securityMode;
|
|
1026
|
-
});
|
|
1027
|
-
if (endpoints_matching_security_mode.length === 0) {
|
|
1028
|
-
return { errCode: node_opcua_status_code_1.StatusCodes.BadSecurityModeRejected };
|
|
1029
|
-
}
|
|
1030
|
-
const endpoints_matching_security_policy = endpoints_matching_security_mode.filter((e) => {
|
|
1031
|
-
return e.securityPolicyUri === channel1.securityHeader.securityPolicyUri;
|
|
1032
|
-
});
|
|
1033
|
-
if (endpoints_matching_security_policy.length === 0) {
|
|
1034
|
-
return { errCode: node_opcua_status_code_1.StatusCodes.BadSecurityPolicyRejected };
|
|
1035
|
-
}
|
|
1036
|
-
if (endpoints_matching_security_policy.length !== 1) {
|
|
1037
|
-
debugLog("endpoints_matching_security_policy= ", endpoints_matching_security_policy.length);
|
|
1038
|
-
}
|
|
1039
|
-
return { errCode: node_opcua_status_code_1.StatusCodes.Good, endpoint: endpoints_matching_security_policy[0] };
|
|
1046
|
+
if (!validate_applicationUri(channel, request)) {
|
|
1047
|
+
return rejectConnection(this, node_opcua_status_code_1.StatusCodes.BadCertificateUriInvalid);
|
|
1040
1048
|
}
|
|
1041
|
-
const { errCode, endpoint } = validate_security_endpoint(channel);
|
|
1049
|
+
const { errCode, endpoint } = validate_security_endpoint(this, request, channel);
|
|
1042
1050
|
if (errCode !== node_opcua_status_code_1.StatusCodes.Good) {
|
|
1043
|
-
return rejectConnection(errCode);
|
|
1051
|
+
return rejectConnection(this, errCode);
|
|
1044
1052
|
}
|
|
1045
1053
|
// see Release 1.02 27 OPC Unified Architecture, Part 4
|
|
1046
|
-
const session =
|
|
1054
|
+
const session = this.createSession({
|
|
1047
1055
|
clientDescription: request.clientDescription,
|
|
1048
1056
|
sessionTimeout: revisedSessionTimeout
|
|
1049
1057
|
});
|
|
@@ -1065,10 +1073,10 @@ class OPCUAServer extends base_server_1.OPCUABaseServer {
|
|
|
1065
1073
|
//
|
|
1066
1074
|
// ( this serverNonce will only be used up to the _on_ActivateSessionRequest
|
|
1067
1075
|
// where a new nonce will be created)
|
|
1068
|
-
session.nonce =
|
|
1076
|
+
session.nonce = this.makeServerNonce();
|
|
1069
1077
|
session.channelId = channel.channelId;
|
|
1070
1078
|
session._attach_channel(channel);
|
|
1071
|
-
const serverCertificateChain =
|
|
1079
|
+
const serverCertificateChain = this.getCertificateChain();
|
|
1072
1080
|
const hasEncryption = true;
|
|
1073
1081
|
// If the securityPolicyUri is None and none of the UserTokenPolicies requires encryption
|
|
1074
1082
|
if (session.channel.securityMode === node_opcua_secure_channel_1.MessageSecurityMode.None) {
|
|
@@ -1102,7 +1110,7 @@ class OPCUAServer extends base_server_1.OPCUABaseServer {
|
|
|
1102
1110
|
// securityPolicyUri, userIdentityTokens, transportProfileUri and securityLevel with all
|
|
1103
1111
|
// other parameters set to null. Only the recommended parameters shall be verified by
|
|
1104
1112
|
// the client.
|
|
1105
|
-
serverEndpoints: _serverEndpointsForCreateSessionResponse(
|
|
1113
|
+
serverEndpoints: _serverEndpointsForCreateSessionResponse(this, session.endpoint.endpointUrl, request.serverUri),
|
|
1106
1114
|
// This parameter is deprecated and the array shall be empty.
|
|
1107
1115
|
serverSoftwareCertificates: null,
|
|
1108
1116
|
// This is a signature generated with the private key associated with the
|
|
@@ -1111,20 +1119,20 @@ class OPCUAServer extends base_server_1.OPCUABaseServer {
|
|
|
1111
1119
|
// The SignatureAlgorithm shall be the AsymmetricSignatureAlgorithm specified in the
|
|
1112
1120
|
// SecurityPolicy for the Endpoint.
|
|
1113
1121
|
// The SignatureData type is defined in 7.30.
|
|
1114
|
-
serverSignature:
|
|
1122
|
+
serverSignature: this.computeServerSignature(channel, request.clientCertificate, request.clientNonce),
|
|
1115
1123
|
// The maximum message size accepted by the server
|
|
1116
1124
|
// The Client Communication Stack should return a Bad_RequestTooLarge error to the
|
|
1117
1125
|
// application if a request message exceeds this limit.
|
|
1118
1126
|
// The value zero indicates that this parameter is not used.
|
|
1119
1127
|
maxRequestMessageSize: 0x4000000
|
|
1120
1128
|
});
|
|
1121
|
-
|
|
1129
|
+
this.emit("create_session", session);
|
|
1122
1130
|
session.on("session_closed", (session1, deleteSubscriptions, reason) => {
|
|
1123
1131
|
(0, node_opcua_assert_1.assert)(typeof reason === "string");
|
|
1124
|
-
if (
|
|
1132
|
+
if (this.isAuditing) {
|
|
1125
1133
|
(0, node_opcua_assert_1.assert)(reason === "Timeout" || reason === "Terminated" || reason === "CloseSession" || reason === "Forcing");
|
|
1126
1134
|
const sourceName = "Session/" + reason;
|
|
1127
|
-
|
|
1135
|
+
this.raiseEvent("AuditSessionEventType", {
|
|
1128
1136
|
/* part 5 - 6.4.3 AuditEventType */
|
|
1129
1137
|
actionTimeStamp: { dataType: "DateTime", value: new Date() },
|
|
1130
1138
|
status: { dataType: "Boolean", value: true },
|
|
@@ -1139,11 +1147,11 @@ class OPCUAServer extends base_server_1.OPCUABaseServer {
|
|
|
1139
1147
|
sessionId: { dataType: "NodeId", value: session1.nodeId }
|
|
1140
1148
|
});
|
|
1141
1149
|
}
|
|
1142
|
-
|
|
1150
|
+
this.emit("session_closed", session1, deleteSubscriptions);
|
|
1143
1151
|
});
|
|
1144
|
-
if (
|
|
1152
|
+
if (this.isAuditing) {
|
|
1145
1153
|
// ------------------------------------------------------------------------------------------------------
|
|
1146
|
-
|
|
1154
|
+
this.raiseEvent("AuditCreateSessionEventType", {
|
|
1147
1155
|
/* part 5 - 6.4.3 AuditEventType */
|
|
1148
1156
|
actionTimeStamp: { dataType: "DateTime", value: new Date() },
|
|
1149
1157
|
status: { dataType: "Boolean", value: true },
|
|
@@ -1168,7 +1176,7 @@ class OPCUAServer extends base_server_1.OPCUABaseServer {
|
|
|
1168
1176
|
clientCertificate: { dataType: "ByteString", value: session.channel.clientCertificate },
|
|
1169
1177
|
// clientCertificateThumbprint
|
|
1170
1178
|
clientCertificateThumbprint: {
|
|
1171
|
-
dataType: "
|
|
1179
|
+
dataType: "String",
|
|
1172
1180
|
value: thumbprint(session.channel.clientCertificate)
|
|
1173
1181
|
}
|
|
1174
1182
|
});
|
|
@@ -1196,13 +1204,12 @@ class OPCUAServer extends base_server_1.OPCUABaseServer {
|
|
|
1196
1204
|
*
|
|
1197
1205
|
*/
|
|
1198
1206
|
_on_ActivateSessionRequest(message, channel) {
|
|
1199
|
-
const server = this;
|
|
1200
1207
|
const request = message.request;
|
|
1201
1208
|
(0, node_opcua_assert_1.assert)(request instanceof node_opcua_service_session_1.ActivateSessionRequest);
|
|
1202
1209
|
// get session from authenticationToken
|
|
1203
1210
|
const authenticationToken = request.requestHeader.authenticationToken;
|
|
1204
|
-
const session =
|
|
1205
|
-
function rejectConnection(statusCode) {
|
|
1211
|
+
const session = this.getSession(authenticationToken);
|
|
1212
|
+
function rejectConnection(server, statusCode) {
|
|
1206
1213
|
if (statusCode === node_opcua_status_code_1.StatusCodes.BadSessionIdInvalid) {
|
|
1207
1214
|
server.engine.incrementRejectedSessionCount();
|
|
1208
1215
|
}
|
|
@@ -1220,7 +1227,7 @@ class OPCUAServer extends base_server_1.OPCUABaseServer {
|
|
|
1220
1227
|
// this may happen when the server has been restarted and a client tries to reconnect, thinking
|
|
1221
1228
|
// that the previous session may still be active
|
|
1222
1229
|
debugLog(chalk.yellow.bold(" Bad Session in _on_ActivateSessionRequest"), authenticationToken.toString());
|
|
1223
|
-
return rejectConnection(node_opcua_status_code_1.StatusCodes.BadSessionIdInvalid);
|
|
1230
|
+
return rejectConnection(this, node_opcua_status_code_1.StatusCodes.BadSessionIdInvalid);
|
|
1224
1231
|
}
|
|
1225
1232
|
// tslint:disable-next-line: no-unused-expression
|
|
1226
1233
|
session.keepAlive ? session.keepAlive() : void 0;
|
|
@@ -1233,7 +1240,7 @@ class OPCUAServer extends base_server_1.OPCUABaseServer {
|
|
|
1233
1240
|
// it looks like session activation is being using a channel that is not the
|
|
1234
1241
|
// one that have been used to create the session
|
|
1235
1242
|
errorLog(" channel.sessionTokens === " + Object.keys(channel.sessionTokens).join(" "));
|
|
1236
|
-
return rejectConnection(node_opcua_status_code_1.StatusCodes.BadSessionNotActivated);
|
|
1243
|
+
return rejectConnection(this, node_opcua_status_code_1.StatusCodes.BadSessionNotActivated);
|
|
1237
1244
|
}
|
|
1238
1245
|
}
|
|
1239
1246
|
// OpcUA 1.02 part 3 $5.6.3.1 ActiveSession Set page 29
|
|
@@ -1249,55 +1256,55 @@ class OPCUAServer extends base_server_1.OPCUABaseServer {
|
|
|
1249
1256
|
const old_channel_cert_thumbprint = thumbprint(session.channel.clientCertificate);
|
|
1250
1257
|
const new_channel_cert_thumbprint = thumbprint(channel.clientCertificate);
|
|
1251
1258
|
if (old_channel_cert_thumbprint !== new_channel_cert_thumbprint) {
|
|
1252
|
-
return rejectConnection(node_opcua_status_code_1.StatusCodes.BadNoValidCertificates); // not sure about this code !
|
|
1259
|
+
return rejectConnection(this, node_opcua_status_code_1.StatusCodes.BadNoValidCertificates); // not sure about this code !
|
|
1253
1260
|
}
|
|
1254
1261
|
// ... In addition the Server shall verify that the Client supplied a UserIdentityToken that is
|
|
1255
1262
|
// identical to the token currently associated with the Session reassign session to new channel.
|
|
1256
1263
|
if (!sameIdentityToken(session.userIdentityToken, request.userIdentityToken)) {
|
|
1257
|
-
return rejectConnection(node_opcua_status_code_1.StatusCodes.BadIdentityChangeNotSupported); // not sure about this code !
|
|
1264
|
+
return rejectConnection(this, node_opcua_status_code_1.StatusCodes.BadIdentityChangeNotSupported); // not sure about this code !
|
|
1258
1265
|
}
|
|
1259
1266
|
}
|
|
1260
1267
|
moveSessionToChannel(session, channel);
|
|
1261
1268
|
}
|
|
1262
1269
|
else if (session.status === "screwed") {
|
|
1263
1270
|
// session has been used before being activated => this should be detected and session should be dismissed.
|
|
1264
|
-
return rejectConnection(node_opcua_status_code_1.StatusCodes.BadSessionClosed);
|
|
1271
|
+
return rejectConnection(this, node_opcua_status_code_1.StatusCodes.BadSessionClosed);
|
|
1265
1272
|
}
|
|
1266
1273
|
else if (session.status === "closed") {
|
|
1267
1274
|
warningLog(chalk.yellow.bold(" Bad Session Closed in _on_ActivateSessionRequest"), authenticationToken.toString());
|
|
1268
|
-
return rejectConnection(node_opcua_status_code_1.StatusCodes.BadSessionClosed);
|
|
1275
|
+
return rejectConnection(this, node_opcua_status_code_1.StatusCodes.BadSessionClosed);
|
|
1269
1276
|
}
|
|
1270
1277
|
// verify clientSignature provided by the client
|
|
1271
|
-
if (!
|
|
1272
|
-
return rejectConnection(node_opcua_status_code_1.StatusCodes.BadApplicationSignatureInvalid);
|
|
1278
|
+
if (!this.verifyClientSignature(session, channel, request.clientSignature)) {
|
|
1279
|
+
return rejectConnection(this, node_opcua_status_code_1.StatusCodes.BadApplicationSignatureInvalid);
|
|
1273
1280
|
}
|
|
1274
1281
|
// userIdentityToken may be missing , assume anonymous access then
|
|
1275
1282
|
request.userIdentityToken = request.userIdentityToken || createAnonymousIdentityToken(session.endpoint);
|
|
1276
1283
|
// check request.userIdentityToken is correct ( expected type and correctly formed)
|
|
1277
|
-
|
|
1284
|
+
this.isValidUserIdentityToken(channel, session, request.userIdentityToken, request.userTokenSignature, session.endpoint, (err, statusCode) => {
|
|
1278
1285
|
if (statusCode !== node_opcua_status_code_1.StatusCodes.Good) {
|
|
1279
1286
|
/* istanbul ignore next */
|
|
1280
1287
|
if (!(statusCode && statusCode instanceof node_opcua_status_code_1.StatusCode)) {
|
|
1281
1288
|
const a = 23;
|
|
1282
1289
|
}
|
|
1283
1290
|
(0, node_opcua_assert_1.assert)(statusCode && statusCode instanceof node_opcua_status_code_1.StatusCode, "expecting statusCode");
|
|
1284
|
-
return rejectConnection(statusCode);
|
|
1291
|
+
return rejectConnection(this, statusCode);
|
|
1285
1292
|
}
|
|
1286
1293
|
session.userIdentityToken = request.userIdentityToken;
|
|
1287
1294
|
// check if user access is granted
|
|
1288
|
-
|
|
1295
|
+
this.isUserAuthorized(channel, session, request.userIdentityToken, (err1, authorized) => {
|
|
1289
1296
|
/* istanbul ignore next */
|
|
1290
1297
|
if (err1) {
|
|
1291
|
-
return rejectConnection(node_opcua_status_code_1.StatusCodes.BadInternalError);
|
|
1298
|
+
return rejectConnection(this, node_opcua_status_code_1.StatusCodes.BadInternalError);
|
|
1292
1299
|
}
|
|
1293
1300
|
if (!authorized) {
|
|
1294
|
-
return rejectConnection(node_opcua_status_code_1.StatusCodes.BadUserAccessDenied);
|
|
1301
|
+
return rejectConnection(this, node_opcua_status_code_1.StatusCodes.BadUserAccessDenied);
|
|
1295
1302
|
}
|
|
1296
1303
|
else {
|
|
1297
1304
|
// extract : OPC UA part 4 - 5.6.3
|
|
1298
1305
|
// Once used, a serverNonce cannot be used again. For that reason, the Server returns a new
|
|
1299
1306
|
// serverNonce each time the ActivateSession Service is called.
|
|
1300
|
-
session.nonce =
|
|
1307
|
+
session.nonce = this.makeServerNonce();
|
|
1301
1308
|
session.status = "active";
|
|
1302
1309
|
response = new node_opcua_service_session_1.ActivateSessionResponse({ serverNonce: session.nonce });
|
|
1303
1310
|
channel.send_response("MSG", response, message);
|
|
@@ -1314,8 +1321,8 @@ class OPCUAServer extends base_server_1.OPCUABaseServer {
|
|
|
1314
1321
|
(0, node_opcua_assert_1.assert)(session.nodeId); // sessionId
|
|
1315
1322
|
// xx assert(session.channel.clientCertificate instanceof Buffer);
|
|
1316
1323
|
(0, node_opcua_assert_1.assert)(session.sessionTimeout > 0);
|
|
1317
|
-
if (
|
|
1318
|
-
|
|
1324
|
+
if (this.isAuditing) {
|
|
1325
|
+
this.raiseEvent("AuditActivateSessionEventType", {
|
|
1319
1326
|
/* part 5 - 6.4.3 AuditEventType */
|
|
1320
1327
|
actionTimeStamp: { dataType: "DateTime", value: new Date() },
|
|
1321
1328
|
status: { dataType: "Boolean", value: true },
|
|
@@ -1349,17 +1356,16 @@ class OPCUAServer extends base_server_1.OPCUABaseServer {
|
|
|
1349
1356
|
secureChannelId: { dataType: "String", value: session.channel.channelId.toString() }
|
|
1350
1357
|
});
|
|
1351
1358
|
}
|
|
1352
|
-
|
|
1359
|
+
this.emit("session_activated", session, userIdentityTokenPasswordRemoved);
|
|
1353
1360
|
}
|
|
1354
1361
|
});
|
|
1355
1362
|
});
|
|
1356
1363
|
}
|
|
1357
1364
|
prepare(message, channel) {
|
|
1358
|
-
const server = this;
|
|
1359
1365
|
const request = message.request;
|
|
1360
1366
|
// --- check that session is correct
|
|
1361
1367
|
const authenticationToken = request.requestHeader.authenticationToken;
|
|
1362
|
-
const session =
|
|
1368
|
+
const session = this.getSession(authenticationToken, /*activeOnly*/ true);
|
|
1363
1369
|
if (!session) {
|
|
1364
1370
|
message.session_statusCode = node_opcua_status_code_1.StatusCodes.BadSessionIdInvalid;
|
|
1365
1371
|
return;
|
|
@@ -1386,19 +1392,19 @@ class OPCUAServer extends base_server_1.OPCUABaseServer {
|
|
|
1386
1392
|
* @param ResponseClass the constructor of the response Class
|
|
1387
1393
|
* @param message
|
|
1388
1394
|
* @param channel
|
|
1389
|
-
* @param
|
|
1390
|
-
* @param
|
|
1391
|
-
* @param
|
|
1392
|
-
* @param
|
|
1393
|
-
* @param
|
|
1394
|
-
* @param
|
|
1395
|
-
* @param
|
|
1395
|
+
* @param actionToPerform
|
|
1396
|
+
* @param actionToPerform.session {ServerSession}
|
|
1397
|
+
* @param actionToPerform.sendResponse
|
|
1398
|
+
* @param actionToPerform.sendResponse.response
|
|
1399
|
+
* @param actionToPerform.sendError
|
|
1400
|
+
* @param actionToPerform.sendError.statusCode
|
|
1401
|
+
* @param actionToPerform.sendError.diagnostics
|
|
1396
1402
|
*
|
|
1397
1403
|
* @private
|
|
1398
1404
|
*/
|
|
1399
|
-
_apply_on_SessionObject(ResponseClass, message, channel,
|
|
1405
|
+
_apply_on_SessionObject(ResponseClass, message, channel, actionToPerform) {
|
|
1400
1406
|
return __awaiter(this, void 0, void 0, function* () {
|
|
1401
|
-
(0, node_opcua_assert_1.assert)(typeof
|
|
1407
|
+
(0, node_opcua_assert_1.assert)(typeof actionToPerform === "function");
|
|
1402
1408
|
function sendResponse(response1) {
|
|
1403
1409
|
try {
|
|
1404
1410
|
(0, node_opcua_assert_1.assert)(response1 instanceof ResponseClass);
|
|
@@ -1461,44 +1467,28 @@ class OPCUAServer extends base_server_1.OPCUABaseServer {
|
|
|
1461
1467
|
message.session.keepAlive();
|
|
1462
1468
|
}
|
|
1463
1469
|
message.session.incrementTotalRequestCount();
|
|
1464
|
-
yield
|
|
1470
|
+
yield actionToPerform(message.session, sendResponse, sendError);
|
|
1465
1471
|
});
|
|
1466
1472
|
}
|
|
1467
|
-
|
|
1468
|
-
* @method _apply_on_Subscription
|
|
1469
|
-
* @param ResponseClass
|
|
1470
|
-
* @param message
|
|
1471
|
-
* @param channel
|
|
1472
|
-
* @param action_to_perform
|
|
1473
|
-
* @private
|
|
1474
|
-
*/
|
|
1475
|
-
_apply_on_Subscription(ResponseClass, message, channel, action_to_perform) {
|
|
1473
|
+
_apply_on_Subscription(ResponseClass, message, channel, actionToPerform) {
|
|
1476
1474
|
return __awaiter(this, void 0, void 0, function* () {
|
|
1477
|
-
(0, node_opcua_assert_1.assert)(typeof
|
|
1475
|
+
(0, node_opcua_assert_1.assert)(typeof actionToPerform === "function");
|
|
1478
1476
|
const request = message.request;
|
|
1479
|
-
(0, node_opcua_assert_1.assert)(
|
|
1477
|
+
(0, node_opcua_assert_1.assert)(Object.prototype.hasOwnProperty.call(request, "subscriptionId"));
|
|
1480
1478
|
this._apply_on_SessionObject(ResponseClass, message, channel, (session, sendResponse, sendError) => __awaiter(this, void 0, void 0, function* () {
|
|
1481
1479
|
const subscription = session.getSubscription(request.subscriptionId);
|
|
1482
1480
|
if (!subscription) {
|
|
1483
1481
|
return sendError(node_opcua_status_code_1.StatusCodes.BadSubscriptionIdInvalid);
|
|
1484
1482
|
}
|
|
1485
1483
|
subscription.resetLifeTimeAndKeepAliveCounters();
|
|
1486
|
-
yield
|
|
1484
|
+
yield actionToPerform(session, subscription, sendResponse, sendError);
|
|
1487
1485
|
}));
|
|
1488
1486
|
});
|
|
1489
1487
|
}
|
|
1490
|
-
|
|
1491
|
-
|
|
1492
|
-
* @param ResponseClass
|
|
1493
|
-
* @param message
|
|
1494
|
-
* @param channel
|
|
1495
|
-
* @param action_to_perform
|
|
1496
|
-
* @private
|
|
1497
|
-
*/
|
|
1498
|
-
_apply_on_SubscriptionIds(ResponseClass, message, channel, action_to_perform) {
|
|
1499
|
-
(0, node_opcua_assert_1.assert)(typeof action_to_perform === "function");
|
|
1488
|
+
_apply_on_SubscriptionIds(ResponseClass, message, channel, actionToPerform) {
|
|
1489
|
+
(0, node_opcua_assert_1.assert)(typeof actionToPerform === "function");
|
|
1500
1490
|
const request = message.request;
|
|
1501
|
-
(0, node_opcua_assert_1.assert)(
|
|
1491
|
+
(0, node_opcua_assert_1.assert)(Object.prototype.hasOwnProperty.call(request, "subscriptionIds"));
|
|
1502
1492
|
this._apply_on_SessionObject(ResponseClass, message, channel, (session, sendResponse, sendError) => __awaiter(this, void 0, void 0, function* () {
|
|
1503
1493
|
const subscriptionIds = request.subscriptionIds;
|
|
1504
1494
|
if (!request.subscriptionIds || request.subscriptionIds.length === 0) {
|
|
@@ -1507,7 +1497,7 @@ class OPCUAServer extends base_server_1.OPCUABaseServer {
|
|
|
1507
1497
|
// if (request.subscriptionIds.length > OPCUAServer.MAX_SUBSCRIPTION) {
|
|
1508
1498
|
// return sendError(StatusCodes.BadTooManyOperations);
|
|
1509
1499
|
// }
|
|
1510
|
-
const results = subscriptionIds.map((subscriptionId) =>
|
|
1500
|
+
const results = subscriptionIds.map((subscriptionId) => actionToPerform(session, subscriptionId));
|
|
1511
1501
|
// resolve potential pending promises ....
|
|
1512
1502
|
for (let i = 0; i < results.length; i++) {
|
|
1513
1503
|
if (results[i].then) {
|
|
@@ -1525,15 +1515,7 @@ class OPCUAServer extends base_server_1.OPCUABaseServer {
|
|
|
1525
1515
|
sendResponse(response);
|
|
1526
1516
|
}));
|
|
1527
1517
|
}
|
|
1528
|
-
|
|
1529
|
-
* @method _apply_on_Subscriptions
|
|
1530
|
-
* @param ResponseClass
|
|
1531
|
-
* @param message
|
|
1532
|
-
* @param channel
|
|
1533
|
-
* @param action_to_perform
|
|
1534
|
-
* @private
|
|
1535
|
-
*/
|
|
1536
|
-
_apply_on_Subscriptions(ResponseClass, message, channel, action_to_perform) {
|
|
1518
|
+
_apply_on_Subscriptions(ResponseClass, message, channel, actionToPerform) {
|
|
1537
1519
|
this._apply_on_SubscriptionIds(ResponseClass, message, channel, (session, subscriptionId) => __awaiter(this, void 0, void 0, function* () {
|
|
1538
1520
|
/* istanbul ignore next */
|
|
1539
1521
|
if (isSubscriptionIdInvalid(subscriptionId)) {
|
|
@@ -1543,13 +1525,11 @@ class OPCUAServer extends base_server_1.OPCUABaseServer {
|
|
|
1543
1525
|
if (!subscription) {
|
|
1544
1526
|
return node_opcua_status_code_1.StatusCodes.BadSubscriptionIdInvalid;
|
|
1545
1527
|
}
|
|
1546
|
-
return
|
|
1528
|
+
return actionToPerform(session, subscription);
|
|
1547
1529
|
}));
|
|
1548
1530
|
}
|
|
1549
1531
|
_closeSession(authenticationToken, deleteSubscriptions, reason) {
|
|
1550
1532
|
return __awaiter(this, void 0, void 0, function* () {
|
|
1551
|
-
const server = this;
|
|
1552
|
-
//
|
|
1553
1533
|
if (deleteSubscriptions && this.options.onDeleteMonitoredItem) {
|
|
1554
1534
|
const session = this.getSession(authenticationToken);
|
|
1555
1535
|
if (session) {
|
|
@@ -1559,7 +1539,7 @@ class OPCUAServer extends base_server_1.OPCUABaseServer {
|
|
|
1559
1539
|
}
|
|
1560
1540
|
}
|
|
1561
1541
|
}
|
|
1562
|
-
yield
|
|
1542
|
+
yield this.engine.closeSession(authenticationToken, deleteSubscriptions, reason);
|
|
1563
1543
|
});
|
|
1564
1544
|
}
|
|
1565
1545
|
/**
|
|
@@ -1569,7 +1549,6 @@ class OPCUAServer extends base_server_1.OPCUABaseServer {
|
|
|
1569
1549
|
* @private
|
|
1570
1550
|
*/
|
|
1571
1551
|
_on_CloseSessionRequest(message, channel) {
|
|
1572
|
-
const server = this;
|
|
1573
1552
|
const request = message.request;
|
|
1574
1553
|
(0, node_opcua_assert_1.assert)(request instanceof node_opcua_service_session_1.CloseSessionRequest);
|
|
1575
1554
|
let response;
|
|
@@ -1606,7 +1585,6 @@ class OPCUAServer extends base_server_1.OPCUABaseServer {
|
|
|
1606
1585
|
* @private
|
|
1607
1586
|
*/
|
|
1608
1587
|
_on_BrowseRequest(message, channel) {
|
|
1609
|
-
const server = this;
|
|
1610
1588
|
const request = message.request;
|
|
1611
1589
|
(0, node_opcua_assert_1.assert)(request instanceof node_opcua_service_browse_1.BrowseRequest);
|
|
1612
1590
|
const diagnostic = {};
|
|
@@ -1614,7 +1592,7 @@ class OPCUAServer extends base_server_1.OPCUABaseServer {
|
|
|
1614
1592
|
let response;
|
|
1615
1593
|
// test view
|
|
1616
1594
|
if (request.view && !request.view.viewId.isEmpty()) {
|
|
1617
|
-
let theView =
|
|
1595
|
+
let theView = this.engine.addressSpace.findNode(request.view.viewId);
|
|
1618
1596
|
if (theView && theView.nodeClass !== node_opcua_data_model_1.NodeClass.View) {
|
|
1619
1597
|
// Error: theView is not a View
|
|
1620
1598
|
diagnostic.localizedText = { text: "Expecting a view here" };
|
|
@@ -1627,16 +1605,16 @@ class OPCUAServer extends base_server_1.OPCUABaseServer {
|
|
|
1627
1605
|
if (!request.nodesToBrowse || request.nodesToBrowse.length === 0) {
|
|
1628
1606
|
return sendError(node_opcua_status_code_1.StatusCodes.BadNothingToDo);
|
|
1629
1607
|
}
|
|
1630
|
-
if (
|
|
1631
|
-
if (request.nodesToBrowse.length >
|
|
1608
|
+
if (this.engine.serverCapabilities.operationLimits.maxNodesPerBrowse > 0) {
|
|
1609
|
+
if (request.nodesToBrowse.length > this.engine.serverCapabilities.operationLimits.maxNodesPerBrowse) {
|
|
1632
1610
|
return sendError(node_opcua_status_code_1.StatusCodes.BadTooManyOperations);
|
|
1633
1611
|
}
|
|
1634
1612
|
}
|
|
1635
1613
|
// limit results to requestedMaxReferencesPerNode further so it never exceed a too big number
|
|
1636
1614
|
const requestedMaxReferencesPerNode = Math.min(9876, request.requestedMaxReferencesPerNode);
|
|
1637
1615
|
(0, node_opcua_assert_1.assert)(request.nodesToBrowse[0].schema.name === "BrowseDescription");
|
|
1638
|
-
const context = new node_opcua_address_space_1.SessionContext({ session, server });
|
|
1639
|
-
const f = (0, util_1.callbackify)(
|
|
1616
|
+
const context = new node_opcua_address_space_1.SessionContext({ session, server: this });
|
|
1617
|
+
const f = (0, util_1.callbackify)(this.engine.browseWithAutomaticExpansion).bind(this.engine);
|
|
1640
1618
|
f(request.nodesToBrowse, context, (err, results) => {
|
|
1641
1619
|
// istanbul ignore next
|
|
1642
1620
|
if (!results) {
|
|
@@ -1644,20 +1622,25 @@ class OPCUAServer extends base_server_1.OPCUABaseServer {
|
|
|
1644
1622
|
}
|
|
1645
1623
|
(0, node_opcua_assert_1.assert)(results[0].schema.name === "BrowseResult");
|
|
1646
1624
|
// handle continuation point and requestedMaxReferencesPerNode
|
|
1647
|
-
const maxBrowseContinuationPoints =
|
|
1625
|
+
const maxBrowseContinuationPoints = this.engine.serverCapabilities.maxBrowseContinuationPoints;
|
|
1648
1626
|
results = results.map((result) => {
|
|
1649
1627
|
(0, node_opcua_assert_1.assert)(!result.continuationPoint);
|
|
1650
1628
|
// istanbul ignore next
|
|
1651
1629
|
if (!session.continuationPointManager) {
|
|
1652
1630
|
return new node_opcua_types_1.BrowseResult({ statusCode: node_opcua_status_code_1.StatusCodes.BadNoContinuationPoints });
|
|
1653
1631
|
}
|
|
1654
|
-
if (session.continuationPointManager.
|
|
1632
|
+
if (session.continuationPointManager.hasReachedMaximum(maxBrowseContinuationPoints)) {
|
|
1655
1633
|
return new node_opcua_types_1.BrowseResult({ statusCode: node_opcua_status_code_1.StatusCodes.BadNoContinuationPoints });
|
|
1656
1634
|
}
|
|
1657
|
-
const truncatedResult = session.continuationPointManager.
|
|
1658
|
-
|
|
1659
|
-
|
|
1660
|
-
|
|
1635
|
+
const truncatedResult = session.continuationPointManager.registerReferences(requestedMaxReferencesPerNode, result.references || [], { continuationPoint: null });
|
|
1636
|
+
let { statusCode } = truncatedResult;
|
|
1637
|
+
const { continuationPoint, values } = truncatedResult;
|
|
1638
|
+
statusCode = result.statusCode;
|
|
1639
|
+
return new node_opcua_types_1.BrowseResult({
|
|
1640
|
+
statusCode,
|
|
1641
|
+
continuationPoint,
|
|
1642
|
+
references: values
|
|
1643
|
+
});
|
|
1661
1644
|
});
|
|
1662
1645
|
response = new node_opcua_service_browse_1.BrowseResponse({
|
|
1663
1646
|
diagnosticInfos: undefined,
|
|
@@ -1677,31 +1660,21 @@ class OPCUAServer extends base_server_1.OPCUABaseServer {
|
|
|
1677
1660
|
const request = message.request;
|
|
1678
1661
|
(0, node_opcua_assert_1.assert)(request instanceof node_opcua_service_browse_1.BrowseNextRequest);
|
|
1679
1662
|
this._apply_on_SessionObject(node_opcua_service_browse_1.BrowseNextResponse, message, channel, (session, sendResponse, sendError) => {
|
|
1680
|
-
let response;
|
|
1681
1663
|
if (!request.continuationPoints || request.continuationPoints.length === 0) {
|
|
1682
1664
|
return sendError(node_opcua_status_code_1.StatusCodes.BadNothingToDo);
|
|
1683
1665
|
}
|
|
1684
|
-
|
|
1685
|
-
|
|
1686
|
-
|
|
1687
|
-
|
|
1688
|
-
|
|
1689
|
-
|
|
1690
|
-
|
|
1691
|
-
|
|
1692
|
-
|
|
1693
|
-
|
|
1694
|
-
}
|
|
1695
|
-
|
|
1696
|
-
// let extract data from continuation points
|
|
1697
|
-
// releaseContinuationPoints = FALSE
|
|
1698
|
-
// passed continuationPoints shall be used to get the next set of
|
|
1699
|
-
// browse information.
|
|
1700
|
-
results = request.continuationPoints.map((continuationPoint) => {
|
|
1701
|
-
return session.continuationPointManager.getNext(continuationPoint);
|
|
1702
|
-
});
|
|
1703
|
-
}
|
|
1704
|
-
response = new node_opcua_service_browse_1.BrowseNextResponse({
|
|
1666
|
+
const results = request.continuationPoints
|
|
1667
|
+
.map((continuationPoint, index) => session.continuationPointManager.getNextReferences(0, {
|
|
1668
|
+
continuationPoint,
|
|
1669
|
+
index,
|
|
1670
|
+
releaseContinuationPoints: request.releaseContinuationPoints
|
|
1671
|
+
}))
|
|
1672
|
+
.map((r) => ({
|
|
1673
|
+
continuationPoint: r.continuationPoint,
|
|
1674
|
+
references: r.values,
|
|
1675
|
+
statusCode: r.statusCode
|
|
1676
|
+
}));
|
|
1677
|
+
const response = new node_opcua_service_browse_1.BrowseNextResponse({
|
|
1705
1678
|
diagnosticInfos: undefined,
|
|
1706
1679
|
results
|
|
1707
1680
|
});
|
|
@@ -1710,11 +1683,10 @@ class OPCUAServer extends base_server_1.OPCUABaseServer {
|
|
|
1710
1683
|
}
|
|
1711
1684
|
// read services
|
|
1712
1685
|
_on_ReadRequest(message, channel) {
|
|
1713
|
-
const server = this;
|
|
1714
1686
|
const request = message.request;
|
|
1715
1687
|
(0, node_opcua_assert_1.assert)(request instanceof node_opcua_service_read_1.ReadRequest);
|
|
1716
1688
|
this._apply_on_SessionObject(node_opcua_service_read_1.ReadResponse, message, channel, (session, sendResponse, sendError) => {
|
|
1717
|
-
const context = new node_opcua_address_space_1.SessionContext({ session, server });
|
|
1689
|
+
const context = new node_opcua_address_space_1.SessionContext({ session, server: this });
|
|
1718
1690
|
let response;
|
|
1719
1691
|
let results = [];
|
|
1720
1692
|
const timestampsToReturn = request.timestampsToReturn;
|
|
@@ -1730,8 +1702,8 @@ class OPCUAServer extends base_server_1.OPCUABaseServer {
|
|
|
1730
1702
|
}
|
|
1731
1703
|
(0, node_opcua_assert_1.assert)(request.nodesToRead[0].schema.name === "ReadValueId");
|
|
1732
1704
|
// limit size of nodesToRead array to maxNodesPerRead
|
|
1733
|
-
if (
|
|
1734
|
-
if (request.nodesToRead.length >
|
|
1705
|
+
if (this.engine.serverCapabilities.operationLimits.maxNodesPerRead > 0) {
|
|
1706
|
+
if (request.nodesToRead.length > this.engine.serverCapabilities.operationLimits.maxNodesPerRead) {
|
|
1735
1707
|
return sendError(node_opcua_status_code_1.StatusCodes.BadTooManyOperations);
|
|
1736
1708
|
}
|
|
1737
1709
|
}
|
|
@@ -1740,9 +1712,9 @@ class OPCUAServer extends base_server_1.OPCUABaseServer {
|
|
|
1740
1712
|
nodeToRead.nodeId = session.resolveRegisteredNode(nodeToRead.nodeId);
|
|
1741
1713
|
}
|
|
1742
1714
|
// ask for a refresh of asynchronous variables
|
|
1743
|
-
|
|
1715
|
+
this.engine.refreshValues(request.nodesToRead, request.maxAge, (err) => {
|
|
1744
1716
|
(0, node_opcua_assert_1.assert)(!err, " error not handled here , fix me");
|
|
1745
|
-
results =
|
|
1717
|
+
results = this.engine.read(context, request);
|
|
1746
1718
|
(0, node_opcua_assert_1.assert)(results[0].schema.name === "DataValue");
|
|
1747
1719
|
(0, node_opcua_assert_1.assert)(results.length === request.nodesToRead.length);
|
|
1748
1720
|
response = new node_opcua_service_read_1.ReadResponse({
|
|
@@ -1758,7 +1730,6 @@ class OPCUAServer extends base_server_1.OPCUABaseServer {
|
|
|
1758
1730
|
}
|
|
1759
1731
|
// read services
|
|
1760
1732
|
_on_HistoryReadRequest(message, channel) {
|
|
1761
|
-
const server = this;
|
|
1762
1733
|
const request = message.request;
|
|
1763
1734
|
(0, node_opcua_assert_1.assert)(request instanceof node_opcua_service_history_1.HistoryReadRequest);
|
|
1764
1735
|
this._apply_on_SessionObject(node_opcua_service_history_1.HistoryReadResponse, message, channel, (session, sendResponse, sendError) => {
|
|
@@ -1773,27 +1744,27 @@ class OPCUAServer extends base_server_1.OPCUABaseServer {
|
|
|
1773
1744
|
}
|
|
1774
1745
|
(0, node_opcua_assert_1.assert)(request.nodesToRead[0].schema.name === "HistoryReadValueId");
|
|
1775
1746
|
// limit size of nodesToRead array to maxNodesPerRead
|
|
1776
|
-
if (
|
|
1777
|
-
if (request.nodesToRead.length >
|
|
1747
|
+
if (this.engine.serverCapabilities.operationLimits.maxNodesPerRead > 0) {
|
|
1748
|
+
if (request.nodesToRead.length > this.engine.serverCapabilities.operationLimits.maxNodesPerRead) {
|
|
1778
1749
|
return sendError(node_opcua_status_code_1.StatusCodes.BadTooManyOperations);
|
|
1779
1750
|
}
|
|
1780
1751
|
}
|
|
1781
1752
|
// todo : handle
|
|
1782
|
-
if (
|
|
1783
|
-
if (request.nodesToRead.length >
|
|
1753
|
+
if (this.engine.serverCapabilities.operationLimits.maxNodesPerHistoryReadData > 0) {
|
|
1754
|
+
if (request.nodesToRead.length > this.engine.serverCapabilities.operationLimits.maxNodesPerHistoryReadData) {
|
|
1784
1755
|
return sendError(node_opcua_status_code_1.StatusCodes.BadTooManyOperations);
|
|
1785
1756
|
}
|
|
1786
1757
|
}
|
|
1787
|
-
if (
|
|
1788
|
-
if (request.nodesToRead.length >
|
|
1758
|
+
if (this.engine.serverCapabilities.operationLimits.maxNodesPerHistoryReadEvents > 0) {
|
|
1759
|
+
if (request.nodesToRead.length > this.engine.serverCapabilities.operationLimits.maxNodesPerHistoryReadEvents) {
|
|
1789
1760
|
return sendError(node_opcua_status_code_1.StatusCodes.BadTooManyOperations);
|
|
1790
1761
|
}
|
|
1791
1762
|
}
|
|
1792
|
-
const context = new node_opcua_address_space_1.SessionContext({ session, server });
|
|
1763
|
+
const context = new node_opcua_address_space_1.SessionContext({ session, server: this });
|
|
1793
1764
|
// ask for a refresh of asynchronous variables
|
|
1794
|
-
|
|
1765
|
+
this.engine.refreshValues(request.nodesToRead, 0, (err) => {
|
|
1795
1766
|
(0, node_opcua_assert_1.assert)(!err, " error not handled here , fix me"); // TODO
|
|
1796
|
-
|
|
1767
|
+
this.engine.historyRead(context, request, (err1, results) => {
|
|
1797
1768
|
if (err1) {
|
|
1798
1769
|
return sendError(node_opcua_status_code_1.StatusCodes.BadHistoryOperationInvalid);
|
|
1799
1770
|
}
|
|
@@ -1827,7 +1798,6 @@ class OPCUAServer extends base_server_1.OPCUABaseServer {
|
|
|
1827
1798
|
// it reports an unconditional success.
|
|
1828
1799
|
*/
|
|
1829
1800
|
_on_WriteRequest(message, channel) {
|
|
1830
|
-
const server = this;
|
|
1831
1801
|
const request = message.request;
|
|
1832
1802
|
(0, node_opcua_assert_1.assert)(request instanceof node_opcua_service_write_1.WriteRequest);
|
|
1833
1803
|
(0, node_opcua_assert_1.assert)(!request.nodesToWrite || Array.isArray(request.nodesToWrite));
|
|
@@ -1836,8 +1806,8 @@ class OPCUAServer extends base_server_1.OPCUABaseServer {
|
|
|
1836
1806
|
if (!request.nodesToWrite || request.nodesToWrite.length === 0) {
|
|
1837
1807
|
return sendError(node_opcua_status_code_1.StatusCodes.BadNothingToDo);
|
|
1838
1808
|
}
|
|
1839
|
-
if (
|
|
1840
|
-
if (request.nodesToWrite.length >
|
|
1809
|
+
if (this.engine.serverCapabilities.operationLimits.maxNodesPerWrite > 0) {
|
|
1810
|
+
if (request.nodesToWrite.length > this.engine.serverCapabilities.operationLimits.maxNodesPerWrite) {
|
|
1841
1811
|
return sendError(node_opcua_status_code_1.StatusCodes.BadTooManyOperations);
|
|
1842
1812
|
}
|
|
1843
1813
|
}
|
|
@@ -1845,9 +1815,9 @@ class OPCUAServer extends base_server_1.OPCUABaseServer {
|
|
|
1845
1815
|
for (const nodeToWrite of request.nodesToWrite) {
|
|
1846
1816
|
nodeToWrite.nodeId = session.resolveRegisteredNode(nodeToWrite.nodeId);
|
|
1847
1817
|
}
|
|
1848
|
-
const context = new node_opcua_address_space_1.SessionContext({ session, server });
|
|
1818
|
+
const context = new node_opcua_address_space_1.SessionContext({ session, server: this });
|
|
1849
1819
|
(0, node_opcua_assert_1.assert)(request.nodesToWrite[0].schema.name === "WriteValue");
|
|
1850
|
-
|
|
1820
|
+
this.engine.write(context, request.nodesToWrite, (err, results) => {
|
|
1851
1821
|
(0, node_opcua_assert_1.assert)(!err);
|
|
1852
1822
|
(0, node_opcua_assert_1.assert)(Array.isArray(results));
|
|
1853
1823
|
(0, node_opcua_assert_1.assert)(results.length === request.nodesToWrite.length);
|
|
@@ -1861,13 +1831,12 @@ class OPCUAServer extends base_server_1.OPCUABaseServer {
|
|
|
1861
1831
|
}
|
|
1862
1832
|
// subscription services
|
|
1863
1833
|
_on_CreateSubscriptionRequest(message, channel) {
|
|
1864
|
-
const
|
|
1865
|
-
const engine = server.engine;
|
|
1834
|
+
const engine = this.engine;
|
|
1866
1835
|
const addressSpace = engine.addressSpace;
|
|
1867
1836
|
const request = message.request;
|
|
1868
1837
|
(0, node_opcua_assert_1.assert)(request instanceof node_opcua_service_subscription_1.CreateSubscriptionRequest);
|
|
1869
1838
|
this._apply_on_SessionObject(node_opcua_service_subscription_1.CreateSubscriptionResponse, message, channel, (session, sendResponse, sendError) => {
|
|
1870
|
-
const context = new node_opcua_address_space_1.SessionContext({ session, server });
|
|
1839
|
+
const context = new node_opcua_address_space_1.SessionContext({ session, server: this });
|
|
1871
1840
|
if (session.currentSubscriptionCount >= OPCUAServer.MAX_SUBSCRIPTION) {
|
|
1872
1841
|
return sendError(node_opcua_status_code_1.StatusCodes.BadTooManySubscriptions);
|
|
1873
1842
|
}
|
|
@@ -1885,16 +1854,15 @@ class OPCUAServer extends base_server_1.OPCUABaseServer {
|
|
|
1885
1854
|
});
|
|
1886
1855
|
}
|
|
1887
1856
|
_on_DeleteSubscriptionsRequest(message, channel) {
|
|
1888
|
-
const server = this;
|
|
1889
1857
|
const request = message.request;
|
|
1890
1858
|
(0, node_opcua_assert_1.assert)(request instanceof node_opcua_service_subscription_1.DeleteSubscriptionsRequest);
|
|
1891
1859
|
this._apply_on_SubscriptionIds(node_opcua_service_subscription_1.DeleteSubscriptionsResponse, message, channel, (session, subscriptionId) => __awaiter(this, void 0, void 0, function* () {
|
|
1892
|
-
let subscription =
|
|
1860
|
+
let subscription = this.engine.findOrphanSubscription(subscriptionId);
|
|
1893
1861
|
// istanbul ignore next
|
|
1894
1862
|
if (subscription) {
|
|
1895
1863
|
warningLog("Deleting an orphan subscription", subscriptionId);
|
|
1896
1864
|
yield this._beforeDeleteSubscription(subscription);
|
|
1897
|
-
return
|
|
1865
|
+
return this.engine.deleteOrphanSubscription(subscription);
|
|
1898
1866
|
}
|
|
1899
1867
|
subscription = session.getSubscription(subscriptionId);
|
|
1900
1868
|
if (subscription) {
|
|
@@ -1914,15 +1882,13 @@ class OPCUAServer extends base_server_1.OPCUABaseServer {
|
|
|
1914
1882
|
// changes since the last Publish response was sent.
|
|
1915
1883
|
// This parameter only applies to MonitoredItems used for monitoring Attribute changes.
|
|
1916
1884
|
//
|
|
1917
|
-
const
|
|
1918
|
-
const engine = server.engine;
|
|
1885
|
+
const engine = this.engine;
|
|
1919
1886
|
const request = message.request;
|
|
1920
1887
|
(0, node_opcua_assert_1.assert)(request instanceof node_opcua_service_subscription_1.TransferSubscriptionsRequest);
|
|
1921
1888
|
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); }));
|
|
1922
1889
|
}
|
|
1923
1890
|
_on_CreateMonitoredItemsRequest(message, channel) {
|
|
1924
|
-
const
|
|
1925
|
-
const engine = server.engine;
|
|
1891
|
+
const engine = this.engine;
|
|
1926
1892
|
const addressSpace = engine.addressSpace;
|
|
1927
1893
|
const request = message.request;
|
|
1928
1894
|
(0, node_opcua_assert_1.assert)(request instanceof node_opcua_service_subscription_1.CreateMonitoredItemsRequest);
|
|
@@ -1934,8 +1900,8 @@ class OPCUAServer extends base_server_1.OPCUABaseServer {
|
|
|
1934
1900
|
if (!request.itemsToCreate || request.itemsToCreate.length === 0) {
|
|
1935
1901
|
return sendError(node_opcua_status_code_1.StatusCodes.BadNothingToDo);
|
|
1936
1902
|
}
|
|
1937
|
-
if (
|
|
1938
|
-
if (request.itemsToCreate.length >
|
|
1903
|
+
if (this.engine.serverCapabilities.operationLimits.maxMonitoredItemsPerCall > 0) {
|
|
1904
|
+
if (request.itemsToCreate.length > this.engine.serverCapabilities.operationLimits.maxMonitoredItemsPerCall) {
|
|
1939
1905
|
return sendError(node_opcua_status_code_1.StatusCodes.BadTooManyOperations);
|
|
1940
1906
|
}
|
|
1941
1907
|
}
|
|
@@ -1983,7 +1949,6 @@ class OPCUAServer extends base_server_1.OPCUABaseServer {
|
|
|
1983
1949
|
}));
|
|
1984
1950
|
}
|
|
1985
1951
|
_on_ModifyMonitoredItemsRequest(message, channel) {
|
|
1986
|
-
const server = this;
|
|
1987
1952
|
const request = message.request;
|
|
1988
1953
|
(0, node_opcua_assert_1.assert)(request instanceof node_opcua_service_subscription_1.ModifyMonitoredItemsRequest);
|
|
1989
1954
|
this._apply_on_Subscription(node_opcua_service_subscription_1.ModifyMonitoredItemsResponse, message, channel, (session, subscription, sendResponse, sendError) => __awaiter(this, void 0, void 0, function* () {
|
|
@@ -1995,8 +1960,8 @@ class OPCUAServer extends base_server_1.OPCUABaseServer {
|
|
|
1995
1960
|
return sendError(node_opcua_status_code_1.StatusCodes.BadNothingToDo);
|
|
1996
1961
|
}
|
|
1997
1962
|
/* istanbul ignore next */
|
|
1998
|
-
if (
|
|
1999
|
-
if (request.itemsToModify.length >
|
|
1963
|
+
if (this.engine.serverCapabilities.operationLimits.maxMonitoredItemsPerCall > 0) {
|
|
1964
|
+
if (request.itemsToModify.length > this.engine.serverCapabilities.operationLimits.maxMonitoredItemsPerCall) {
|
|
2000
1965
|
return sendError(node_opcua_status_code_1.StatusCodes.BadTooManyOperations);
|
|
2001
1966
|
}
|
|
2002
1967
|
}
|
|
@@ -2040,7 +2005,6 @@ class OPCUAServer extends base_server_1.OPCUABaseServer {
|
|
|
2040
2005
|
}));
|
|
2041
2006
|
}
|
|
2042
2007
|
_on_DeleteMonitoredItemsRequest(message, channel) {
|
|
2043
|
-
const server = this;
|
|
2044
2008
|
const request = message.request;
|
|
2045
2009
|
(0, node_opcua_assert_1.assert)(request instanceof node_opcua_service_subscription_1.DeleteMonitoredItemsRequest);
|
|
2046
2010
|
this._apply_on_Subscription(node_opcua_service_subscription_1.DeleteMonitoredItemsResponse, message, channel, (session, subscription, sendResponse, sendError) => __awaiter(this, void 0, void 0, function* () {
|
|
@@ -2049,8 +2013,8 @@ class OPCUAServer extends base_server_1.OPCUABaseServer {
|
|
|
2049
2013
|
return sendError(node_opcua_status_code_1.StatusCodes.BadNothingToDo);
|
|
2050
2014
|
}
|
|
2051
2015
|
/* istanbul ignore next */
|
|
2052
|
-
if (
|
|
2053
|
-
if (request.monitoredItemIds.length >
|
|
2016
|
+
if (this.engine.serverCapabilities.operationLimits.maxMonitoredItemsPerCall > 0) {
|
|
2017
|
+
if (request.monitoredItemIds.length > this.engine.serverCapabilities.operationLimits.maxMonitoredItemsPerCall) {
|
|
2054
2018
|
return sendError(node_opcua_status_code_1.StatusCodes.BadTooManyOperations);
|
|
2055
2019
|
}
|
|
2056
2020
|
}
|
|
@@ -2078,7 +2042,6 @@ class OPCUAServer extends base_server_1.OPCUABaseServer {
|
|
|
2078
2042
|
}));
|
|
2079
2043
|
}
|
|
2080
2044
|
_on_SetTriggeringRequest(message, channel) {
|
|
2081
|
-
const server = this;
|
|
2082
2045
|
const request = message.request;
|
|
2083
2046
|
(0, node_opcua_assert_1.assert)(request instanceof node_opcua_service_subscription_1.SetTriggeringRequest);
|
|
2084
2047
|
this._apply_on_Subscription(node_opcua_service_subscription_1.SetTriggeringResponse, message, channel, (session, subscription, sendResponse, sendError) => __awaiter(this, void 0, void 0, function* () {
|
|
@@ -2092,8 +2055,8 @@ class OPCUAServer extends base_server_1.OPCUABaseServer {
|
|
|
2092
2055
|
*
|
|
2093
2056
|
*/
|
|
2094
2057
|
const maxElements = (linksToAdd ? linksToAdd.length : 0) + (linksToRemove ? linksToRemove.length : 0);
|
|
2095
|
-
if (
|
|
2096
|
-
if (maxElements >
|
|
2058
|
+
if (this.engine.serverCapabilities.operationLimits.maxMonitoredItemsPerCall > 0) {
|
|
2059
|
+
if (maxElements > this.engine.serverCapabilities.operationLimits.maxMonitoredItemsPerCall) {
|
|
2097
2060
|
return sendError(node_opcua_status_code_1.StatusCodes.BadTooManyOperations);
|
|
2098
2061
|
}
|
|
2099
2062
|
}
|
|
@@ -2144,7 +2107,6 @@ class OPCUAServer extends base_server_1.OPCUABaseServer {
|
|
|
2144
2107
|
// Bad_SubscriptionIdInvalid
|
|
2145
2108
|
// Bad_MonitoringModeInvalid
|
|
2146
2109
|
_on_SetMonitoringModeRequest(message, channel) {
|
|
2147
|
-
const server = this;
|
|
2148
2110
|
const request = message.request;
|
|
2149
2111
|
(0, node_opcua_assert_1.assert)(request instanceof node_opcua_service_subscription_1.SetMonitoringModeRequest);
|
|
2150
2112
|
this._apply_on_Subscription(node_opcua_service_subscription_1.SetMonitoringModeResponse, message, channel, (session, subscription, sendResponse, sendError) => __awaiter(this, void 0, void 0, function* () {
|
|
@@ -2153,8 +2115,8 @@ class OPCUAServer extends base_server_1.OPCUABaseServer {
|
|
|
2153
2115
|
return sendError(node_opcua_status_code_1.StatusCodes.BadNothingToDo);
|
|
2154
2116
|
}
|
|
2155
2117
|
/* istanbul ignore next */
|
|
2156
|
-
if (
|
|
2157
|
-
if (request.monitoredItemIds.length >
|
|
2118
|
+
if (this.engine.serverCapabilities.operationLimits.maxMonitoredItemsPerCall > 0) {
|
|
2119
|
+
if (request.monitoredItemIds.length > this.engine.serverCapabilities.operationLimits.maxMonitoredItemsPerCall) {
|
|
2158
2120
|
return sendError(node_opcua_status_code_1.StatusCodes.BadTooManyOperations);
|
|
2159
2121
|
}
|
|
2160
2122
|
}
|
|
@@ -2180,18 +2142,17 @@ class OPCUAServer extends base_server_1.OPCUABaseServer {
|
|
|
2180
2142
|
_on_TranslateBrowsePathsToNodeIdsRequest(message, channel) {
|
|
2181
2143
|
const request = message.request;
|
|
2182
2144
|
(0, node_opcua_assert_1.assert)(request instanceof node_opcua_service_translate_browse_path_1.TranslateBrowsePathsToNodeIdsRequest);
|
|
2183
|
-
const server = this;
|
|
2184
2145
|
this._apply_on_SessionObject(node_opcua_service_translate_browse_path_1.TranslateBrowsePathsToNodeIdsResponse, message, channel, (session, sendResponse, sendError) => __awaiter(this, void 0, void 0, function* () {
|
|
2185
2146
|
if (!request.browsePaths || request.browsePaths.length === 0) {
|
|
2186
2147
|
return sendError(node_opcua_status_code_1.StatusCodes.BadNothingToDo);
|
|
2187
2148
|
}
|
|
2188
|
-
if (
|
|
2149
|
+
if (this.engine.serverCapabilities.operationLimits.maxNodesPerTranslateBrowsePathsToNodeIds > 0) {
|
|
2189
2150
|
if (request.browsePaths.length >
|
|
2190
|
-
|
|
2151
|
+
this.engine.serverCapabilities.operationLimits.maxNodesPerTranslateBrowsePathsToNodeIds) {
|
|
2191
2152
|
return sendError(node_opcua_status_code_1.StatusCodes.BadTooManyOperations);
|
|
2192
2153
|
}
|
|
2193
2154
|
}
|
|
2194
|
-
const browsePathsResults = request.browsePaths.map((browsePath) =>
|
|
2155
|
+
const browsePathsResults = request.browsePaths.map((browsePath) => this.engine.browsePath(browsePath));
|
|
2195
2156
|
const response = new node_opcua_service_translate_browse_path_1.TranslateBrowsePathsToNodeIdsResponse({
|
|
2196
2157
|
diagnosticInfos: null,
|
|
2197
2158
|
results: browsePathsResults
|
|
@@ -2205,7 +2166,6 @@ class OPCUAServer extends base_server_1.OPCUABaseServer {
|
|
|
2205
2166
|
// Bad_TooManyOperations See Table 165 for the description of this result code.
|
|
2206
2167
|
//
|
|
2207
2168
|
_on_CallRequest(message, channel) {
|
|
2208
|
-
const server = this;
|
|
2209
2169
|
const request = message.request;
|
|
2210
2170
|
(0, node_opcua_assert_1.assert)(request instanceof node_opcua_service_call_1.CallRequest);
|
|
2211
2171
|
this._apply_on_SessionObject(node_opcua_service_call_1.CallResponse, message, channel, (session, sendResponse, sendError) => {
|
|
@@ -2215,14 +2175,14 @@ class OPCUAServer extends base_server_1.OPCUABaseServer {
|
|
|
2215
2175
|
}
|
|
2216
2176
|
// the MaxNodesPerMethodCall Property indicates the maximum size of the methodsToCall array when
|
|
2217
2177
|
// a Client calls the Call Service.
|
|
2218
|
-
let maxNodesPerMethodCall =
|
|
2178
|
+
let maxNodesPerMethodCall = this.engine.serverCapabilities.operationLimits.maxNodesPerMethodCall;
|
|
2219
2179
|
maxNodesPerMethodCall = maxNodesPerMethodCall <= 0 ? 1000 : maxNodesPerMethodCall;
|
|
2220
2180
|
if (request.methodsToCall.length > maxNodesPerMethodCall) {
|
|
2221
2181
|
return sendError(node_opcua_status_code_1.StatusCodes.BadTooManyOperations);
|
|
2222
2182
|
}
|
|
2223
2183
|
/* jshint validthis: true */
|
|
2224
|
-
const addressSpace =
|
|
2225
|
-
const context = new node_opcua_address_space_1.SessionContext({ session, server });
|
|
2184
|
+
const addressSpace = this.engine.addressSpace;
|
|
2185
|
+
const context = new node_opcua_address_space_1.SessionContext({ session, server: this });
|
|
2226
2186
|
async.map(request.methodsToCall, node_opcua_address_space_1.callMethodHelper.bind(null, context, addressSpace), (err, results) => {
|
|
2227
2187
|
/* istanbul ignore next */
|
|
2228
2188
|
if (err) {
|
|
@@ -2237,7 +2197,6 @@ class OPCUAServer extends base_server_1.OPCUABaseServer {
|
|
|
2237
2197
|
});
|
|
2238
2198
|
}
|
|
2239
2199
|
_on_RegisterNodesRequest(message, channel) {
|
|
2240
|
-
const server = this;
|
|
2241
2200
|
const request = message.request;
|
|
2242
2201
|
(0, node_opcua_assert_1.assert)(request instanceof node_opcua_service_register_node_1.RegisterNodesRequest);
|
|
2243
2202
|
this._apply_on_SessionObject(node_opcua_service_register_node_1.RegisterNodesResponse, message, channel, (session, sendResponse, sendError) => {
|
|
@@ -2246,8 +2205,8 @@ class OPCUAServer extends base_server_1.OPCUABaseServer {
|
|
|
2246
2205
|
response = new node_opcua_service_register_node_1.RegisterNodesResponse({ responseHeader: { serviceResult: node_opcua_status_code_1.StatusCodes.BadNothingToDo } });
|
|
2247
2206
|
return sendResponse(response);
|
|
2248
2207
|
}
|
|
2249
|
-
if (
|
|
2250
|
-
if (request.nodesToRegister.length >
|
|
2208
|
+
if (this.engine.serverCapabilities.operationLimits.maxNodesPerRegisterNodes > 0) {
|
|
2209
|
+
if (request.nodesToRegister.length > this.engine.serverCapabilities.operationLimits.maxNodesPerRegisterNodes) {
|
|
2251
2210
|
return sendError(node_opcua_status_code_1.StatusCodes.BadTooManyOperations);
|
|
2252
2211
|
}
|
|
2253
2212
|
}
|
|
@@ -2266,7 +2225,6 @@ class OPCUAServer extends base_server_1.OPCUABaseServer {
|
|
|
2266
2225
|
});
|
|
2267
2226
|
}
|
|
2268
2227
|
_on_UnregisterNodesRequest(message, channel) {
|
|
2269
|
-
const server = this;
|
|
2270
2228
|
const request = message.request;
|
|
2271
2229
|
(0, node_opcua_assert_1.assert)(request instanceof node_opcua_service_register_node_1.UnregisterNodesRequest);
|
|
2272
2230
|
this._apply_on_SessionObject(node_opcua_service_register_node_1.UnregisterNodesResponse, message, channel, (session, sendResponse, sendError) => {
|
|
@@ -2276,8 +2234,8 @@ class OPCUAServer extends base_server_1.OPCUABaseServer {
|
|
|
2276
2234
|
response = new node_opcua_service_register_node_1.UnregisterNodesResponse({ responseHeader: { serviceResult: node_opcua_status_code_1.StatusCodes.BadNothingToDo } });
|
|
2277
2235
|
return sendResponse(response);
|
|
2278
2236
|
}
|
|
2279
|
-
if (
|
|
2280
|
-
if (request.nodesToUnregister.length >
|
|
2237
|
+
if (this.engine.serverCapabilities.operationLimits.maxNodesPerRegisterNodes > 0) {
|
|
2238
|
+
if (request.nodesToUnregister.length > this.engine.serverCapabilities.operationLimits.maxNodesPerRegisterNodes) {
|
|
2281
2239
|
return sendError(node_opcua_status_code_1.StatusCodes.BadTooManyOperations);
|
|
2282
2240
|
}
|
|
2283
2241
|
}
|
|
@@ -2398,8 +2356,6 @@ OPCUAServer.fallbackSessionName = "Client didn't provide a meaningful sessionNam
|
|
|
2398
2356
|
* the maximum number of subscription that can be created per server
|
|
2399
2357
|
*/
|
|
2400
2358
|
OPCUAServer.MAX_SUBSCRIPTION = 50;
|
|
2401
|
-
// tslint:disable:no-var-requires
|
|
2402
|
-
const thenify = require("thenify");
|
|
2403
2359
|
const opts = { multiArgs: false };
|
|
2404
2360
|
OPCUAServer.prototype.start = thenify.withCallback(OPCUAServer.prototype.start, opts);
|
|
2405
2361
|
OPCUAServer.prototype.initialize = thenify.withCallback(OPCUAServer.prototype.initialize, opts);
|