node-opcua-server 2.112.0 → 2.114.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 +228 -257
- package/dist/addressSpace_accessor.js.map +1 -1
- package/dist/base_server.js +86 -101
- package/dist/base_server.js.map +1 -1
- package/dist/helper.js +1 -2
- package/dist/helper.js.map +1 -1
- package/dist/monitored_item.js +36 -59
- package/dist/monitored_item.js.map +1 -1
- package/dist/node_sampler.js +1 -0
- package/dist/node_sampler.js.map +1 -1
- package/dist/opcua_server.js +330 -355
- package/dist/opcua_server.js.map +1 -1
- package/dist/register_server_manager.js +5 -8
- package/dist/register_server_manager.js.map +1 -1
- package/dist/server_end_point.js +2 -3
- package/dist/server_end_point.js.map +1 -1
- package/dist/server_engine.js +121 -155
- package/dist/server_engine.js.map +1 -1
- package/dist/server_publish_engine.js +41 -50
- package/dist/server_publish_engine.js.map +1 -1
- package/dist/server_session.js +11 -26
- package/dist/server_session.js.map +1 -1
- package/dist/server_subscription.js +22 -35
- package/dist/server_subscription.js.map +1 -1
- package/dist/user_manager.js +22 -36
- package/dist/user_manager.js.map +1 -1
- package/dist/user_manager_ua.js +1 -2
- package/dist/user_manager_ua.js.map +1 -1
- package/dist/validate_filter.js +3 -2
- package/dist/validate_filter.js.map +1 -1
- package/package.json +45 -45
- package/source/addressSpace_accessor.ts +24 -4
- package/source/monitored_item.ts +14 -17
- package/source/node_sampler.ts +1 -0
- package/source/server_engine.ts +2 -2
- package/source/server_publish_engine.ts +2 -0
- package/source/server_session.ts +1 -0
- package/source/server_subscription.ts +5 -0
- package/source/validate_filter.ts +4 -2
package/dist/opcua_server.js
CHANGED
|
@@ -29,15 +29,6 @@ var __importStar = (this && this.__importStar) || function (mod) {
|
|
|
29
29
|
__setModuleDefault(result, mod);
|
|
30
30
|
return result;
|
|
31
31
|
};
|
|
32
|
-
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
33
|
-
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
34
|
-
return new (P || (P = Promise))(function (resolve, reject) {
|
|
35
|
-
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
36
|
-
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
37
|
-
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
38
|
-
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
39
|
-
});
|
|
40
|
-
};
|
|
41
32
|
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
42
33
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
43
34
|
};
|
|
@@ -138,13 +129,11 @@ function moveSessionToChannel(session, channel) {
|
|
|
138
129
|
session._attach_channel(channel);
|
|
139
130
|
(0, node_opcua_assert_1.assert)(session.channel.channelId === channel.channelId);
|
|
140
131
|
}
|
|
141
|
-
function _attempt_to_close_some_old_unactivated_session(server) {
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
}
|
|
147
|
-
});
|
|
132
|
+
async function _attempt_to_close_some_old_unactivated_session(server) {
|
|
133
|
+
const session = server.engine.getOldestInactiveSession();
|
|
134
|
+
if (session) {
|
|
135
|
+
await server.engine.closeSession(session.authenticationToken, false, "Forcing");
|
|
136
|
+
}
|
|
148
137
|
}
|
|
149
138
|
function getRequiredEndpointInfo(endpoint) {
|
|
150
139
|
(0, node_opcua_assert_1.assert)(endpoint instanceof node_opcua_types_1.EndpointDescription);
|
|
@@ -412,7 +401,6 @@ function _installRegisterServerManager(self) {
|
|
|
412
401
|
});
|
|
413
402
|
}
|
|
414
403
|
function validate_applicationUri(channel, request) {
|
|
415
|
-
var _a, _b;
|
|
416
404
|
const applicationUri = request.clientDescription.applicationUri;
|
|
417
405
|
const clientCertificate = request.clientCertificate;
|
|
418
406
|
// if session is insecure there is no need to check certificate information
|
|
@@ -423,7 +411,7 @@ function validate_applicationUri(channel, request) {
|
|
|
423
411
|
return true; // can't check
|
|
424
412
|
}
|
|
425
413
|
const e = (0, node_opcua_crypto_1.exploreCertificate)(clientCertificate);
|
|
426
|
-
const uniformResourceIdentifier =
|
|
414
|
+
const uniformResourceIdentifier = e.tbsCertificate.extensions.subjectAltName?.uniformResourceIdentifier ?? null;
|
|
427
415
|
const applicationUriFromCert = uniformResourceIdentifier && uniformResourceIdentifier.length > 0 ? uniformResourceIdentifier[0] : null;
|
|
428
416
|
/* istanbul ignore next */
|
|
429
417
|
if (applicationUriFromCert !== applicationUri) {
|
|
@@ -434,7 +422,6 @@ function validate_applicationUri(channel, request) {
|
|
|
434
422
|
return applicationUriFromCert === applicationUri;
|
|
435
423
|
}
|
|
436
424
|
function validate_security_endpoint(server, request, channel) {
|
|
437
|
-
var _a;
|
|
438
425
|
debugLog("validate_security_endpoint = ", request.endpointUrl);
|
|
439
426
|
let endpoints = server._get_endpoints(request.endpointUrl);
|
|
440
427
|
// endpointUrl String The network address that the Client used to access the Session Endpoint.
|
|
@@ -447,7 +434,7 @@ function validate_security_endpoint(server, request, channel) {
|
|
|
447
434
|
// ToDo: check endpointUrl validity and emit an AuditUrlMismatchEventType event if not
|
|
448
435
|
// sometime endpoints have a extra leading "/" that can be ignored
|
|
449
436
|
// don't be too harsh.
|
|
450
|
-
if (endpoints.length === 0 &&
|
|
437
|
+
if (endpoints.length === 0 && request.endpointUrl?.endsWith("/")) {
|
|
451
438
|
endpoints = server._get_endpoints(request.endpointUrl.slice(0, -1));
|
|
452
439
|
}
|
|
453
440
|
if (endpoints.length === 0) {
|
|
@@ -630,7 +617,10 @@ class OPCUAServer extends base_server_1.OPCUABaseServer {
|
|
|
630
617
|
*/
|
|
631
618
|
this.maxConnectionsPerEndpoint = options.maxConnectionsPerEndpoint || default_maxConnectionsPerEndpoint;
|
|
632
619
|
// build Info
|
|
633
|
-
const buildInfo =
|
|
620
|
+
const buildInfo = {
|
|
621
|
+
...default_build_info,
|
|
622
|
+
...options.buildInfo
|
|
623
|
+
};
|
|
634
624
|
// repair product name
|
|
635
625
|
buildInfo.productUri = buildInfo.productUri || this.serverInfo.productUri;
|
|
636
626
|
this.serverInfo.productUri = this.serverInfo.productUri || buildInfo.productUri;
|
|
@@ -654,7 +644,7 @@ class OPCUAServer extends base_server_1.OPCUABaseServer {
|
|
|
654
644
|
}
|
|
655
645
|
// note: we need to delay initialization of endpoint as certain resources
|
|
656
646
|
// such as %FQDN% might not be ready yet at this stage
|
|
657
|
-
this._delayInit = () =>
|
|
647
|
+
this._delayInit = async () => {
|
|
658
648
|
/* istanbul ignore next */
|
|
659
649
|
if (!options) {
|
|
660
650
|
throw new Error("Internal Error");
|
|
@@ -695,18 +685,18 @@ class OPCUAServer extends base_server_1.OPCUABaseServer {
|
|
|
695
685
|
// });
|
|
696
686
|
// });
|
|
697
687
|
}
|
|
698
|
-
}
|
|
688
|
+
};
|
|
699
689
|
}
|
|
700
690
|
initialize(...args) {
|
|
701
691
|
const done = args[0];
|
|
702
692
|
(0, node_opcua_assert_1.assert)(!this.initialized, "server is already initialized"); // already initialized ?
|
|
703
|
-
this._preInitTask.push(() =>
|
|
693
|
+
this._preInitTask.push(async () => {
|
|
704
694
|
/* istanbul ignore else */
|
|
705
695
|
if (this._delayInit) {
|
|
706
|
-
|
|
696
|
+
await this._delayInit();
|
|
707
697
|
this._delayInit = undefined;
|
|
708
698
|
}
|
|
709
|
-
})
|
|
699
|
+
});
|
|
710
700
|
this.performPreInitialization()
|
|
711
701
|
.then(() => {
|
|
712
702
|
OPCUAServer.registry.register(this);
|
|
@@ -772,15 +762,15 @@ class OPCUAServer extends base_server_1.OPCUABaseServer {
|
|
|
772
762
|
debugLog("OPCUAServer is now un-registering itself from the discovery server " + this.buildInfo);
|
|
773
763
|
this.registerServerManager.stop((err) => {
|
|
774
764
|
debugLog("OPCUAServer unregistered from discovery server", err);
|
|
775
|
-
setTimeout(() =>
|
|
776
|
-
|
|
765
|
+
setTimeout(async () => {
|
|
766
|
+
await this.engine.shutdown();
|
|
777
767
|
debugLog("OPCUAServer#shutdown: started");
|
|
778
768
|
base_server_1.OPCUABaseServer.prototype.shutdown.call(this, (err1) => {
|
|
779
769
|
debugLog("OPCUAServer#shutdown: completed");
|
|
780
770
|
this.dispose();
|
|
781
771
|
callback(err1);
|
|
782
772
|
});
|
|
783
|
-
}
|
|
773
|
+
}, timeout);
|
|
784
774
|
});
|
|
785
775
|
}
|
|
786
776
|
dispose() {
|
|
@@ -977,7 +967,7 @@ class OPCUAServer extends base_server_1.OPCUABaseServer {
|
|
|
977
967
|
node_opcua_status_code_1.StatusCodes.BadCertificateUseNotAllowed.equals(certificateStatus) ||
|
|
978
968
|
node_opcua_status_code_1.StatusCodes.BadSecurityChecksFailed.equals(certificateStatus) ||
|
|
979
969
|
!node_opcua_status_code_1.StatusCodes.Good.equals(certificateStatus))) {
|
|
980
|
-
debugLog("isValidX509IdentityToken => certificateStatus = ", certificateStatus
|
|
970
|
+
debugLog("isValidX509IdentityToken => certificateStatus = ", certificateStatus?.toString());
|
|
981
971
|
return callback(null, node_opcua_status_code_1.StatusCodes.BadIdentityTokenRejected);
|
|
982
972
|
}
|
|
983
973
|
if (node_opcua_status_code_1.StatusCodes.Good !== certificateStatus) {
|
|
@@ -1082,171 +1072,151 @@ class OPCUAServer extends base_server_1.OPCUABaseServer {
|
|
|
1082
1072
|
}
|
|
1083
1073
|
// session services
|
|
1084
1074
|
// eslint-disable-next-line max-statements
|
|
1085
|
-
_on_CreateSessionRequest(message, channel) {
|
|
1086
|
-
|
|
1087
|
-
|
|
1088
|
-
|
|
1089
|
-
|
|
1090
|
-
|
|
1091
|
-
|
|
1092
|
-
|
|
1093
|
-
|
|
1094
|
-
|
|
1095
|
-
|
|
1096
|
-
|
|
1097
|
-
|
|
1098
|
-
|
|
1099
|
-
|
|
1100
|
-
|
|
1101
|
-
|
|
1102
|
-
|
|
1103
|
-
|
|
1104
|
-
|
|
1105
|
-
|
|
1106
|
-
|
|
1107
|
-
|
|
1108
|
-
|
|
1109
|
-
|
|
1110
|
-
|
|
1111
|
-
|
|
1112
|
-
|
|
1113
|
-
|
|
1114
|
-
|
|
1115
|
-
|
|
1116
|
-
|
|
1117
|
-
|
|
1118
|
-
|
|
1119
|
-
|
|
1120
|
-
|
|
1121
|
-
|
|
1122
|
-
|
|
1123
|
-
|
|
1124
|
-
|
|
1125
|
-
|
|
1126
|
-
|
|
1127
|
-
|
|
1128
|
-
if (
|
|
1129
|
-
|
|
1130
|
-
errorLog(chalk_1.default.red("SERVER with secure connection: Missing or invalid client Nonce "), request.clientNonce && request.clientNonce.toString("hex"));
|
|
1131
|
-
return rejectConnection(this, node_opcua_status_code_1.StatusCodes.BadNonceInvalid);
|
|
1132
|
-
}
|
|
1133
|
-
}
|
|
1134
|
-
if ((0, node_opcua_secure_channel_1.nonceAlreadyBeenUsed)(request.clientNonce)) {
|
|
1135
|
-
errorLog(chalk_1.default.red("SERVER with secure connection: None has already been used"), request.clientNonce && request.clientNonce.toString("hex"));
|
|
1075
|
+
async _on_CreateSessionRequest(message, channel) {
|
|
1076
|
+
const request = message.request;
|
|
1077
|
+
(0, node_opcua_assert_1.assert)(request instanceof node_opcua_service_session_1.CreateSessionRequest);
|
|
1078
|
+
function rejectConnection(server, statusCode) {
|
|
1079
|
+
server.engine.incrementSecurityRejectedSessionCount();
|
|
1080
|
+
const response1 = new node_opcua_types_1.ServiceFault({
|
|
1081
|
+
responseHeader: { serviceResult: statusCode }
|
|
1082
|
+
});
|
|
1083
|
+
channel.send_response("MSG", response1, message);
|
|
1084
|
+
// and close !
|
|
1085
|
+
}
|
|
1086
|
+
// From OPCUA V1.03 Part 4 5.6.2 CreateSession
|
|
1087
|
+
// A Server application should limit the number of Sessions. To protect against misbehaving Clients and denial
|
|
1088
|
+
// of service attacks, the Server shall close the oldest Session that is not activated before reaching the
|
|
1089
|
+
// maximum number of supported Sessions
|
|
1090
|
+
if (this.currentSessionCount >= this.engine.serverCapabilities.maxSessions) {
|
|
1091
|
+
await _attempt_to_close_some_old_unactivated_session(this);
|
|
1092
|
+
}
|
|
1093
|
+
// check if session count hasn't reach the maximum allowed sessions
|
|
1094
|
+
if (this.currentSessionCount >= this.engine.serverCapabilities.maxSessions) {
|
|
1095
|
+
return rejectConnection(this, node_opcua_status_code_1.StatusCodes.BadTooManySessions);
|
|
1096
|
+
}
|
|
1097
|
+
// Release 1.03 OPC Unified Architecture, Part 4 page 24 - CreateSession Parameters
|
|
1098
|
+
// client should prove a sessionName
|
|
1099
|
+
// Session name is a Human readable string that identifies the Session. The Server makes this name and the
|
|
1100
|
+
// sessionId visible in its AddressSpace for diagnostic purposes. The Client should provide a name that is
|
|
1101
|
+
// unique for the instance of the Client.
|
|
1102
|
+
// If this parameter is not specified the Server shall assign a value.
|
|
1103
|
+
if (utils.isNullOrUndefined(request.sessionName)) {
|
|
1104
|
+
// see also #198
|
|
1105
|
+
// let's the server assign a sessionName for this lazy client.
|
|
1106
|
+
debugLog("assigning OPCUAServer.fallbackSessionName because client's sessionName is null ", OPCUAServer.fallbackSessionName);
|
|
1107
|
+
request.sessionName = OPCUAServer.fallbackSessionName;
|
|
1108
|
+
}
|
|
1109
|
+
// Duration Requested maximum number of milliseconds that a Session should remain open without activity.
|
|
1110
|
+
// If the Client fails to issue a Service request within this interval, then the Server shall automatically
|
|
1111
|
+
// terminate the Client Session.
|
|
1112
|
+
const revisedSessionTimeout = _adjust_session_timeout(request.requestedSessionTimeout);
|
|
1113
|
+
// Release 1.02 page 27 OPC Unified Architecture, Part 4: CreateSession.clientNonce
|
|
1114
|
+
// A random number that should never be used in any other request. This number shall have a minimum length of 32
|
|
1115
|
+
// bytes. Profiles may increase the required length. The Server shall use this value to prove possession of
|
|
1116
|
+
// its application instance Certificate in the response.
|
|
1117
|
+
if (!request.clientNonce || request.clientNonce.length < 32) {
|
|
1118
|
+
if (channel.securityMode !== node_opcua_secure_channel_1.MessageSecurityMode.None) {
|
|
1119
|
+
errorLog(chalk_1.default.red("SERVER with secure connection: Missing or invalid client Nonce "), request.clientNonce && request.clientNonce.toString("hex"));
|
|
1136
1120
|
return rejectConnection(this, node_opcua_status_code_1.StatusCodes.BadNonceInvalid);
|
|
1137
1121
|
}
|
|
1138
|
-
|
|
1139
|
-
|
|
1140
|
-
|
|
1141
|
-
|
|
1142
|
-
|
|
1143
|
-
|
|
1144
|
-
|
|
1145
|
-
|
|
1146
|
-
|
|
1147
|
-
|
|
1148
|
-
|
|
1149
|
-
|
|
1150
|
-
|
|
1151
|
-
|
|
1152
|
-
|
|
1153
|
-
|
|
1154
|
-
|
|
1155
|
-
|
|
1156
|
-
|
|
1157
|
-
|
|
1158
|
-
|
|
1159
|
-
|
|
1160
|
-
|
|
1161
|
-
|
|
1162
|
-
|
|
1163
|
-
|
|
1164
|
-
|
|
1165
|
-
|
|
1166
|
-
|
|
1167
|
-
|
|
1168
|
-
|
|
1169
|
-
|
|
1170
|
-
|
|
1171
|
-
|
|
1172
|
-
|
|
1173
|
-
|
|
1174
|
-
|
|
1175
|
-
|
|
1176
|
-
|
|
1177
|
-
|
|
1178
|
-
|
|
1179
|
-
|
|
1180
|
-
|
|
1181
|
-
|
|
1182
|
-
|
|
1183
|
-
|
|
1184
|
-
|
|
1185
|
-
|
|
1186
|
-
|
|
1187
|
-
|
|
1188
|
-
|
|
1189
|
-
|
|
1190
|
-
|
|
1191
|
-
|
|
1192
|
-
|
|
1193
|
-
|
|
1194
|
-
|
|
1195
|
-
|
|
1196
|
-
|
|
1197
|
-
|
|
1198
|
-
|
|
1199
|
-
|
|
1200
|
-
|
|
1201
|
-
|
|
1202
|
-
|
|
1203
|
-
|
|
1204
|
-
|
|
1205
|
-
|
|
1206
|
-
|
|
1207
|
-
|
|
1208
|
-
|
|
1209
|
-
|
|
1210
|
-
|
|
1211
|
-
|
|
1212
|
-
|
|
1213
|
-
|
|
1214
|
-
|
|
1215
|
-
|
|
1216
|
-
|
|
1217
|
-
|
|
1218
|
-
|
|
1219
|
-
|
|
1220
|
-
|
|
1221
|
-
|
|
1222
|
-
|
|
1223
|
-
|
|
1224
|
-
|
|
1225
|
-
|
|
1226
|
-
|
|
1227
|
-
|
|
1228
|
-
|
|
1229
|
-
|
|
1230
|
-
|
|
1231
|
-
|
|
1232
|
-
actionTimeStamp: { dataType: "DateTime", value: new Date() },
|
|
1233
|
-
status: { dataType: "Boolean", value: true },
|
|
1234
|
-
serverId: { dataType: "String", value: "" },
|
|
1235
|
-
// ClientAuditEntryId contains the human-readable AuditEntryId defined in Part 3.
|
|
1236
|
-
clientAuditEntryId: { dataType: "String", value: "" },
|
|
1237
|
-
// The ClientUserId identifies the user of the client requesting an action. The ClientUserId can be
|
|
1238
|
-
// obtained from the UserIdentityToken passed in the ActivateSession call.
|
|
1239
|
-
clientUserId: { dataType: "String", value: "" },
|
|
1240
|
-
sourceName: { dataType: "String", value: sourceName },
|
|
1241
|
-
/* part 5 - 6.4.7 AuditSessionEventType */
|
|
1242
|
-
sessionId: { dataType: "NodeId", value: session1.nodeId }
|
|
1243
|
-
});
|
|
1244
|
-
}
|
|
1245
|
-
this.emit("session_closed", session1, deleteSubscriptions);
|
|
1246
|
-
});
|
|
1122
|
+
}
|
|
1123
|
+
if ((0, node_opcua_secure_channel_1.nonceAlreadyBeenUsed)(request.clientNonce)) {
|
|
1124
|
+
errorLog(chalk_1.default.red("SERVER with secure connection: None has already been used"), request.clientNonce && request.clientNonce.toString("hex"));
|
|
1125
|
+
return rejectConnection(this, node_opcua_status_code_1.StatusCodes.BadNonceInvalid);
|
|
1126
|
+
}
|
|
1127
|
+
// check application spoofing
|
|
1128
|
+
// check if applicationUri in createSessionRequest matches applicationUri in client Certificate
|
|
1129
|
+
if (!validate_applicationUri(channel, request)) {
|
|
1130
|
+
return rejectConnection(this, node_opcua_status_code_1.StatusCodes.BadCertificateUriInvalid);
|
|
1131
|
+
}
|
|
1132
|
+
const { errCode, endpoint } = validate_security_endpoint(this, request, channel);
|
|
1133
|
+
if (errCode !== node_opcua_status_code_1.StatusCodes.Good) {
|
|
1134
|
+
return rejectConnection(this, errCode);
|
|
1135
|
+
}
|
|
1136
|
+
// see Release 1.02 27 OPC Unified Architecture, Part 4
|
|
1137
|
+
const session = this.createSession({
|
|
1138
|
+
clientDescription: request.clientDescription,
|
|
1139
|
+
sessionTimeout: revisedSessionTimeout,
|
|
1140
|
+
server: this
|
|
1141
|
+
});
|
|
1142
|
+
session.endpoint = endpoint;
|
|
1143
|
+
(0, node_opcua_assert_1.assert)(session);
|
|
1144
|
+
(0, node_opcua_assert_1.assert)(session.sessionTimeout === revisedSessionTimeout);
|
|
1145
|
+
session.clientDescription = request.clientDescription;
|
|
1146
|
+
session.sessionName = request.sessionName || `<unknown session name ${unnamed_session_count++}>`;
|
|
1147
|
+
// Depending upon on the SecurityPolicy and the SecurityMode of the SecureChannel, the exchange of
|
|
1148
|
+
// ApplicationInstanceCertificates and Nonces may be optional and the signatures may be empty. See
|
|
1149
|
+
// Part 7 for the definition of SecurityPolicies and the handling of these parameters
|
|
1150
|
+
// serverNonce:
|
|
1151
|
+
// A random number that should never be used in any other request.
|
|
1152
|
+
// This number shall have a minimum length of 32 bytes.
|
|
1153
|
+
// The Client shall use this value to prove possession of its application instance
|
|
1154
|
+
// Certificate in the ActivateSession request.
|
|
1155
|
+
// This value may also be used to prove possession of the userIdentityToken it
|
|
1156
|
+
// specified in the ActivateSession request.
|
|
1157
|
+
//
|
|
1158
|
+
// ( this serverNonce will only be used up to the _on_ActivateSessionRequest
|
|
1159
|
+
// where a new nonce will be created)
|
|
1160
|
+
session.nonce = this.makeServerNonce();
|
|
1161
|
+
session.channelId = channel.channelId;
|
|
1162
|
+
session._attach_channel(channel);
|
|
1163
|
+
const serverCertificateChain = this.getCertificateChain();
|
|
1164
|
+
const hasEncryption = true;
|
|
1165
|
+
// If the securityPolicyUri is None and none of the UserTokenPolicies requires encryption
|
|
1166
|
+
if (session.channel.securityMode === node_opcua_secure_channel_1.MessageSecurityMode.None) {
|
|
1167
|
+
// ToDo: Check that none of our insecure endpoint has a a UserTokenPolicy that require encryption
|
|
1168
|
+
// and set hasEncryption = false under this condition
|
|
1169
|
+
}
|
|
1170
|
+
const response = new node_opcua_service_session_1.CreateSessionResponse({
|
|
1171
|
+
// A identifier which uniquely identifies the session.
|
|
1172
|
+
sessionId: session.nodeId,
|
|
1173
|
+
// A unique identifier assigned by the Server to the Session.
|
|
1174
|
+
// The token used to authenticate the client in subsequent requests.
|
|
1175
|
+
authenticationToken: session.authenticationToken,
|
|
1176
|
+
revisedSessionTimeout,
|
|
1177
|
+
serverNonce: session.nonce,
|
|
1178
|
+
// serverCertificate: type ApplicationServerCertificate
|
|
1179
|
+
// The application instance Certificate issued to the Server.
|
|
1180
|
+
// A Server shall prove possession by using the private key to sign the Nonce provided
|
|
1181
|
+
// by the Client in the request. The Client shall verify that this Certificate is the same as
|
|
1182
|
+
// the one it used to create the SecureChannel.
|
|
1183
|
+
// The ApplicationInstanceCertificate type is defined in OpCUA 1.03 part 4 - $7.2 page 108
|
|
1184
|
+
// If the securityPolicyUri is None and none of the UserTokenPolicies requires
|
|
1185
|
+
// encryption, the Server shall not send an ApplicationInstanceCertificate and the Client
|
|
1186
|
+
// shall ignore the ApplicationInstanceCertificate.
|
|
1187
|
+
serverCertificate: hasEncryption ? serverCertificateChain : undefined,
|
|
1188
|
+
// The endpoints provided by the server.
|
|
1189
|
+
// The Server shall return a set of EndpointDescriptions available for the serverUri
|
|
1190
|
+
// specified in the request.[...]
|
|
1191
|
+
// The Client shall verify this list with the list from a Discovery Endpoint if it used a Discovery
|
|
1192
|
+
// Endpoint to fetch the EndpointDescriptions.
|
|
1193
|
+
// It is recommended that Servers only include the endpointUrl, securityMode,
|
|
1194
|
+
// securityPolicyUri, userIdentityTokens, transportProfileUri and securityLevel with all
|
|
1195
|
+
// other parameters set to null. Only the recommended parameters shall be verified by
|
|
1196
|
+
// the client.
|
|
1197
|
+
serverEndpoints: _serverEndpointsForCreateSessionResponse(this, session.endpoint.endpointUrl, request.serverUri),
|
|
1198
|
+
// This parameter is deprecated and the array shall be empty.
|
|
1199
|
+
serverSoftwareCertificates: null,
|
|
1200
|
+
// This is a signature generated with the private key associated with the
|
|
1201
|
+
// serverCertificate. This parameter is calculated by appending the clientNonce to the
|
|
1202
|
+
// clientCertificate and signing the resulting sequence of bytes.
|
|
1203
|
+
// The SignatureAlgorithm shall be the AsymmetricSignatureAlgorithm specified in the
|
|
1204
|
+
// SecurityPolicy for the Endpoint.
|
|
1205
|
+
// The SignatureData type is defined in 7.30.
|
|
1206
|
+
serverSignature: this.computeServerSignature(channel, request.clientCertificate, request.clientNonce),
|
|
1207
|
+
// The maximum message size accepted by the server
|
|
1208
|
+
// The Client Communication Stack should return a Bad_RequestTooLarge error to the
|
|
1209
|
+
// application if a request message exceeds this limit.
|
|
1210
|
+
// The value zero indicates that this parameter is not used.
|
|
1211
|
+
maxRequestMessageSize: 0x4000000
|
|
1212
|
+
});
|
|
1213
|
+
this.emit("create_session", session);
|
|
1214
|
+
session.on("session_closed", (session1, deleteSubscriptions, reason) => {
|
|
1215
|
+
(0, node_opcua_assert_1.assert)(typeof reason === "string");
|
|
1247
1216
|
if (this.isAuditing) {
|
|
1248
|
-
|
|
1249
|
-
|
|
1217
|
+
(0, node_opcua_assert_1.assert)(reason === "Timeout" || reason === "Terminated" || reason === "CloseSession" || reason === "Forcing");
|
|
1218
|
+
const sourceName = "Session/" + reason;
|
|
1219
|
+
this.raiseEvent("AuditSessionEventType", {
|
|
1250
1220
|
/* part 5 - 6.4.3 AuditEventType */
|
|
1251
1221
|
actionTimeStamp: { dataType: "DateTime", value: new Date() },
|
|
1252
1222
|
status: { dataType: "Boolean", value: true },
|
|
@@ -1256,30 +1226,48 @@ class OPCUAServer extends base_server_1.OPCUABaseServer {
|
|
|
1256
1226
|
// The ClientUserId identifies the user of the client requesting an action. The ClientUserId can be
|
|
1257
1227
|
// obtained from the UserIdentityToken passed in the ActivateSession call.
|
|
1258
1228
|
clientUserId: { dataType: "String", value: "" },
|
|
1259
|
-
sourceName: { dataType: "String", value:
|
|
1229
|
+
sourceName: { dataType: "String", value: sourceName },
|
|
1260
1230
|
/* part 5 - 6.4.7 AuditSessionEventType */
|
|
1261
|
-
sessionId: { dataType: "NodeId", value:
|
|
1262
|
-
/* part 5 - 6.4.8 AuditCreateSessionEventType */
|
|
1263
|
-
// SecureChannelId shall uniquely identify the SecureChannel. The application shall use the same
|
|
1264
|
-
// identifier in all AuditEvents related to the Session Service Set (AuditCreateSessionEventType,
|
|
1265
|
-
// AuditActivateSessionEventType and their subtypes) and the SecureChannel Service Set
|
|
1266
|
-
// (AuditChannelEventType and its subtypes
|
|
1267
|
-
secureChannelId: { dataType: "String", value: session.channel.channelId.toString() },
|
|
1268
|
-
// Duration
|
|
1269
|
-
revisedSessionTimeout: { dataType: "Duration", value: session.sessionTimeout },
|
|
1270
|
-
// clientCertificate
|
|
1271
|
-
clientCertificate: { dataType: "ByteString", value: session.channel.clientCertificate },
|
|
1272
|
-
// clientCertificateThumbprint
|
|
1273
|
-
clientCertificateThumbprint: {
|
|
1274
|
-
dataType: "String",
|
|
1275
|
-
value: thumbprint(session.channel.clientCertificate)
|
|
1276
|
-
}
|
|
1231
|
+
sessionId: { dataType: "NodeId", value: session1.nodeId }
|
|
1277
1232
|
});
|
|
1278
1233
|
}
|
|
1279
|
-
|
|
1280
|
-
(0, node_opcua_assert_1.assert)(response.authenticationToken);
|
|
1281
|
-
channel.send_response("MSG", response, message);
|
|
1234
|
+
this.emit("session_closed", session1, deleteSubscriptions);
|
|
1282
1235
|
});
|
|
1236
|
+
if (this.isAuditing) {
|
|
1237
|
+
// ------------------------------------------------------------------------------------------------------
|
|
1238
|
+
this.raiseEvent("AuditCreateSessionEventType", {
|
|
1239
|
+
/* part 5 - 6.4.3 AuditEventType */
|
|
1240
|
+
actionTimeStamp: { dataType: "DateTime", value: new Date() },
|
|
1241
|
+
status: { dataType: "Boolean", value: true },
|
|
1242
|
+
serverId: { dataType: "String", value: "" },
|
|
1243
|
+
// ClientAuditEntryId contains the human-readable AuditEntryId defined in Part 3.
|
|
1244
|
+
clientAuditEntryId: { dataType: "String", value: "" },
|
|
1245
|
+
// The ClientUserId identifies the user of the client requesting an action. The ClientUserId can be
|
|
1246
|
+
// obtained from the UserIdentityToken passed in the ActivateSession call.
|
|
1247
|
+
clientUserId: { dataType: "String", value: "" },
|
|
1248
|
+
sourceName: { dataType: "String", value: "Session/CreateSession" },
|
|
1249
|
+
/* part 5 - 6.4.7 AuditSessionEventType */
|
|
1250
|
+
sessionId: { dataType: "NodeId", value: session.nodeId },
|
|
1251
|
+
/* part 5 - 6.4.8 AuditCreateSessionEventType */
|
|
1252
|
+
// SecureChannelId shall uniquely identify the SecureChannel. The application shall use the same
|
|
1253
|
+
// identifier in all AuditEvents related to the Session Service Set (AuditCreateSessionEventType,
|
|
1254
|
+
// AuditActivateSessionEventType and their subtypes) and the SecureChannel Service Set
|
|
1255
|
+
// (AuditChannelEventType and its subtypes
|
|
1256
|
+
secureChannelId: { dataType: "String", value: session.channel.channelId.toString() },
|
|
1257
|
+
// Duration
|
|
1258
|
+
revisedSessionTimeout: { dataType: "Duration", value: session.sessionTimeout },
|
|
1259
|
+
// clientCertificate
|
|
1260
|
+
clientCertificate: { dataType: "ByteString", value: session.channel.clientCertificate },
|
|
1261
|
+
// clientCertificateThumbprint
|
|
1262
|
+
clientCertificateThumbprint: {
|
|
1263
|
+
dataType: "String",
|
|
1264
|
+
value: thumbprint(session.channel.clientCertificate)
|
|
1265
|
+
}
|
|
1266
|
+
});
|
|
1267
|
+
}
|
|
1268
|
+
// -----------------------------------------------------------------------------------------------------------
|
|
1269
|
+
(0, node_opcua_assert_1.assert)(response.authenticationToken);
|
|
1270
|
+
channel.send_response("MSG", response, message);
|
|
1283
1271
|
}
|
|
1284
1272
|
// TODO : implement this:
|
|
1285
1273
|
//
|
|
@@ -1459,96 +1447,92 @@ class OPCUAServer extends base_server_1.OPCUABaseServer {
|
|
|
1459
1447
|
*
|
|
1460
1448
|
* @private
|
|
1461
1449
|
*/
|
|
1462
|
-
_apply_on_SessionObject(ResponseClass, message, channel, actionToPerform) {
|
|
1463
|
-
|
|
1464
|
-
|
|
1465
|
-
|
|
1466
|
-
|
|
1467
|
-
|
|
1468
|
-
|
|
1469
|
-
|
|
1470
|
-
message.session.incrementRequestTotalCounter(counterName);
|
|
1471
|
-
}
|
|
1472
|
-
return channel.send_response("MSG", response1, message);
|
|
1450
|
+
async _apply_on_SessionObject(ResponseClass, message, channel, actionToPerform) {
|
|
1451
|
+
(0, node_opcua_assert_1.assert)(typeof actionToPerform === "function");
|
|
1452
|
+
function sendResponse(response1) {
|
|
1453
|
+
try {
|
|
1454
|
+
(0, node_opcua_assert_1.assert)(response1 instanceof ResponseClass || response1 instanceof node_opcua_types_1.ServiceFault);
|
|
1455
|
+
if (message.session) {
|
|
1456
|
+
const counterName = ResponseClass.schema.name.replace("Response", "");
|
|
1457
|
+
message.session.incrementRequestTotalCounter(counterName);
|
|
1473
1458
|
}
|
|
1474
|
-
|
|
1475
|
-
|
|
1476
|
-
|
|
1477
|
-
|
|
1478
|
-
|
|
1479
|
-
|
|
1480
|
-
}
|
|
1459
|
+
return channel.send_response("MSG", response1, message);
|
|
1460
|
+
}
|
|
1461
|
+
catch (err) {
|
|
1462
|
+
warningLog(err);
|
|
1463
|
+
// istanbul ignore next
|
|
1464
|
+
if (util_1.types.isNativeError(err)) {
|
|
1481
1465
|
// istanbul ignore next
|
|
1482
|
-
|
|
1466
|
+
errorLog("Internal error in issuing response\nplease contact support@sterfive.com", message.request.toString(), "\n", response1.toString());
|
|
1483
1467
|
}
|
|
1468
|
+
// istanbul ignore next
|
|
1469
|
+
throw err;
|
|
1484
1470
|
}
|
|
1485
|
-
|
|
1486
|
-
|
|
1487
|
-
|
|
1488
|
-
|
|
1489
|
-
return g_sendError(channel, message, ResponseClass, statusCode);
|
|
1471
|
+
}
|
|
1472
|
+
function sendError(statusCode) {
|
|
1473
|
+
if (message.session) {
|
|
1474
|
+
message.session.incrementRequestErrorCounter(ResponseClass.schema.name.replace("Response", ""));
|
|
1490
1475
|
}
|
|
1491
|
-
|
|
1492
|
-
|
|
1493
|
-
|
|
1494
|
-
|
|
1495
|
-
|
|
1496
|
-
|
|
1497
|
-
|
|
1498
|
-
|
|
1499
|
-
|
|
1500
|
-
|
|
1501
|
-
|
|
1502
|
-
|
|
1503
|
-
|
|
1504
|
-
|
|
1505
|
-
|
|
1506
|
-
|
|
1507
|
-
|
|
1508
|
-
|
|
1509
|
-
|
|
1510
|
-
|
|
1511
|
-
|
|
1512
|
-
|
|
1513
|
-
|
|
1514
|
-
|
|
1515
|
-
|
|
1516
|
-
|
|
1517
|
-
|
|
1518
|
-
|
|
1519
|
-
|
|
1520
|
-
|
|
1521
|
-
|
|
1522
|
-
|
|
1523
|
-
|
|
1524
|
-
|
|
1525
|
-
|
|
1526
|
-
|
|
1527
|
-
|
|
1528
|
-
message.session.
|
|
1529
|
-
|
|
1530
|
-
|
|
1476
|
+
return g_sendError(channel, message, ResponseClass, statusCode);
|
|
1477
|
+
}
|
|
1478
|
+
let response;
|
|
1479
|
+
/* istanbul ignore next */
|
|
1480
|
+
if (!message.session || message.session_statusCode !== node_opcua_status_code_1.StatusCodes.Good) {
|
|
1481
|
+
const errMessage = "INVALID SESSION !! ";
|
|
1482
|
+
response = new ResponseClass({ responseHeader: { serviceResult: message.session_statusCode } });
|
|
1483
|
+
debugLog(chalk_1.default.red.bold(errMessage), chalk_1.default.yellow(message.session_statusCode.toString()), response.constructor.name);
|
|
1484
|
+
return sendResponse(response);
|
|
1485
|
+
}
|
|
1486
|
+
(0, node_opcua_assert_1.assert)(message.session_statusCode.isGood());
|
|
1487
|
+
// OPC UA Specification 1.02 part 4 page 26
|
|
1488
|
+
// When a Session is terminated, all outstanding requests on the Session are aborted and
|
|
1489
|
+
// Bad_SessionClosed StatusCodes are returned to the Client. In addition, the Server deletes the entry
|
|
1490
|
+
// for the Client from its SessionDiagnostics Array Variable and notifies any other Clients who were
|
|
1491
|
+
// subscribed to this entry.
|
|
1492
|
+
if (message.session.status === "closed") {
|
|
1493
|
+
// note : use StatusCodes.BadSessionClosed , for pending message for this session
|
|
1494
|
+
return sendError(node_opcua_status_code_1.StatusCodes.BadSessionIdInvalid);
|
|
1495
|
+
}
|
|
1496
|
+
if (message.session.status === "new") {
|
|
1497
|
+
// mark session as being screwed ! so it cannot be activated anymore
|
|
1498
|
+
message.session.status = "screwed";
|
|
1499
|
+
return sendError(node_opcua_status_code_1.StatusCodes.BadSessionNotActivated);
|
|
1500
|
+
}
|
|
1501
|
+
if (message.session.status !== "active") {
|
|
1502
|
+
// mark session as being screwed ! so it cannot be activated anymore
|
|
1503
|
+
message.session.status = "screwed";
|
|
1504
|
+
// note : use StatusCodes.BadSessionClosed , for pending message for this session
|
|
1505
|
+
return sendError(node_opcua_status_code_1.StatusCodes.BadSessionIdInvalid);
|
|
1506
|
+
}
|
|
1507
|
+
// lets also reset the session watchdog so it doesn't
|
|
1508
|
+
// (Sessions are terminated by the Server automatically if the Client fails to issue a Service
|
|
1509
|
+
// request on the Session within the timeout period negotiated by the Server in the
|
|
1510
|
+
// CreateSession Service response. )
|
|
1511
|
+
if (message.session.keepAlive) {
|
|
1512
|
+
(0, node_opcua_assert_1.assert)(typeof message.session.keepAlive === "function");
|
|
1513
|
+
message.session.keepAlive();
|
|
1514
|
+
}
|
|
1515
|
+
message.session.incrementTotalRequestCount();
|
|
1516
|
+
await actionToPerform(message.session, sendResponse, sendError);
|
|
1531
1517
|
}
|
|
1532
|
-
_apply_on_Subscription(ResponseClass, message, channel, actionToPerform) {
|
|
1533
|
-
|
|
1534
|
-
|
|
1535
|
-
|
|
1536
|
-
|
|
1537
|
-
|
|
1538
|
-
|
|
1539
|
-
|
|
1540
|
-
|
|
1541
|
-
|
|
1542
|
-
|
|
1543
|
-
yield actionToPerform(session, subscription, sendResponse, sendError);
|
|
1544
|
-
}));
|
|
1518
|
+
async _apply_on_Subscription(ResponseClass, message, channel, actionToPerform) {
|
|
1519
|
+
(0, node_opcua_assert_1.assert)(typeof actionToPerform === "function");
|
|
1520
|
+
const request = message.request;
|
|
1521
|
+
(0, node_opcua_assert_1.assert)(Object.prototype.hasOwnProperty.call(request, "subscriptionId"));
|
|
1522
|
+
this._apply_on_SessionObject(ResponseClass, message, channel, async (session, sendResponse, sendError) => {
|
|
1523
|
+
const subscription = session.getSubscription(request.subscriptionId);
|
|
1524
|
+
if (!subscription) {
|
|
1525
|
+
return sendError(node_opcua_status_code_1.StatusCodes.BadSubscriptionIdInvalid);
|
|
1526
|
+
}
|
|
1527
|
+
subscription.resetLifeTimeAndKeepAliveCounters();
|
|
1528
|
+
await actionToPerform(session, subscription, sendResponse, sendError);
|
|
1545
1529
|
});
|
|
1546
1530
|
}
|
|
1547
1531
|
_apply_on_SubscriptionIds(ResponseClass, message, channel, actionToPerform) {
|
|
1548
1532
|
(0, node_opcua_assert_1.assert)(typeof actionToPerform === "function");
|
|
1549
1533
|
const request = message.request;
|
|
1550
1534
|
(0, node_opcua_assert_1.assert)(Object.prototype.hasOwnProperty.call(request, "subscriptionIds"));
|
|
1551
|
-
this._apply_on_SessionObject(ResponseClass, message, channel, (session, sendResponse, sendError) =>
|
|
1535
|
+
this._apply_on_SessionObject(ResponseClass, message, channel, async (session, sendResponse, sendError) => {
|
|
1552
1536
|
const subscriptionIds = request.subscriptionIds;
|
|
1553
1537
|
if (!request.subscriptionIds || request.subscriptionIds.length === 0) {
|
|
1554
1538
|
return sendError(node_opcua_status_code_1.StatusCodes.BadNothingToDo);
|
|
@@ -1557,7 +1541,7 @@ class OPCUAServer extends base_server_1.OPCUABaseServer {
|
|
|
1557
1541
|
// resolve potential pending promises ....
|
|
1558
1542
|
for (let i = 0; i < results.length; i++) {
|
|
1559
1543
|
if (results[i].then) {
|
|
1560
|
-
results[i] =
|
|
1544
|
+
results[i] = await results[i];
|
|
1561
1545
|
}
|
|
1562
1546
|
}
|
|
1563
1547
|
const response = new ResponseClass({
|
|
@@ -1569,10 +1553,10 @@ class OPCUAServer extends base_server_1.OPCUABaseServer {
|
|
|
1569
1553
|
results
|
|
1570
1554
|
});
|
|
1571
1555
|
sendResponse(response);
|
|
1572
|
-
})
|
|
1556
|
+
});
|
|
1573
1557
|
}
|
|
1574
1558
|
_apply_on_Subscriptions(ResponseClass, message, channel, actionToPerform) {
|
|
1575
|
-
this._apply_on_SubscriptionIds(ResponseClass, message, channel, (session, subscriptionId) =>
|
|
1559
|
+
this._apply_on_SubscriptionIds(ResponseClass, message, channel, async (session, subscriptionId) => {
|
|
1576
1560
|
/* istanbul ignore next */
|
|
1577
1561
|
if (isSubscriptionIdInvalid(subscriptionId)) {
|
|
1578
1562
|
return node_opcua_status_code_1.StatusCodes.BadSubscriptionIdInvalid;
|
|
@@ -1582,21 +1566,19 @@ class OPCUAServer extends base_server_1.OPCUABaseServer {
|
|
|
1582
1566
|
return node_opcua_status_code_1.StatusCodes.BadSubscriptionIdInvalid;
|
|
1583
1567
|
}
|
|
1584
1568
|
return actionToPerform(session, subscription);
|
|
1585
|
-
})
|
|
1586
|
-
}
|
|
1587
|
-
_closeSession(authenticationToken, deleteSubscriptions, reason) {
|
|
1588
|
-
|
|
1589
|
-
|
|
1590
|
-
|
|
1591
|
-
|
|
1592
|
-
|
|
1593
|
-
|
|
1594
|
-
yield subscription.applyOnMonitoredItem(this.options.onDeleteMonitoredItem.bind(null, subscription));
|
|
1595
|
-
}
|
|
1569
|
+
});
|
|
1570
|
+
}
|
|
1571
|
+
async _closeSession(authenticationToken, deleteSubscriptions, reason) {
|
|
1572
|
+
if (deleteSubscriptions && this.options.onDeleteMonitoredItem) {
|
|
1573
|
+
const session = this.getSession(authenticationToken);
|
|
1574
|
+
if (session) {
|
|
1575
|
+
const subscriptions = session.publishEngine.subscriptions;
|
|
1576
|
+
for (const subscription of subscriptions) {
|
|
1577
|
+
await subscription.applyOnMonitoredItem(this.options.onDeleteMonitoredItem.bind(null, subscription));
|
|
1596
1578
|
}
|
|
1597
1579
|
}
|
|
1598
|
-
|
|
1599
|
-
|
|
1580
|
+
}
|
|
1581
|
+
await this.engine.closeSession(authenticationToken, deleteSubscriptions, reason);
|
|
1600
1582
|
}
|
|
1601
1583
|
/**
|
|
1602
1584
|
* @method _on_CloseSessionRequest
|
|
@@ -1624,9 +1606,9 @@ class OPCUAServer extends base_server_1.OPCUABaseServer {
|
|
|
1624
1606
|
}
|
|
1625
1607
|
// session has been created but not activated !
|
|
1626
1608
|
const wasNotActivated = session.status === "new";
|
|
1627
|
-
(() =>
|
|
1609
|
+
(async () => {
|
|
1628
1610
|
try {
|
|
1629
|
-
|
|
1611
|
+
await this._closeSession(request.requestHeader.authenticationToken, request.deleteSubscriptions, "CloseSession");
|
|
1630
1612
|
// if (false && wasNotActivated) {
|
|
1631
1613
|
// return sendError(StatusCodes.BadSessionNotActivated);
|
|
1632
1614
|
// }
|
|
@@ -1636,7 +1618,7 @@ class OPCUAServer extends base_server_1.OPCUABaseServer {
|
|
|
1636
1618
|
catch (err) {
|
|
1637
1619
|
sendError(node_opcua_status_code_1.StatusCodes.BadInternalError);
|
|
1638
1620
|
}
|
|
1639
|
-
})
|
|
1621
|
+
})();
|
|
1640
1622
|
}
|
|
1641
1623
|
// browse services
|
|
1642
1624
|
/**
|
|
@@ -1906,20 +1888,20 @@ class OPCUAServer extends base_server_1.OPCUABaseServer {
|
|
|
1906
1888
|
_on_DeleteSubscriptionsRequest(message, channel) {
|
|
1907
1889
|
const request = message.request;
|
|
1908
1890
|
(0, node_opcua_assert_1.assert)(request instanceof node_opcua_service_subscription_1.DeleteSubscriptionsRequest);
|
|
1909
|
-
this._apply_on_SubscriptionIds(node_opcua_service_subscription_1.DeleteSubscriptionsResponse, message, channel, (session, subscriptionId) =>
|
|
1891
|
+
this._apply_on_SubscriptionIds(node_opcua_service_subscription_1.DeleteSubscriptionsResponse, message, channel, async (session, subscriptionId) => {
|
|
1910
1892
|
let subscription = this.engine.findOrphanSubscription(subscriptionId);
|
|
1911
1893
|
// istanbul ignore next
|
|
1912
1894
|
if (subscription) {
|
|
1913
1895
|
warningLog("Deleting an orphan subscription", subscriptionId);
|
|
1914
|
-
|
|
1896
|
+
await this._beforeDeleteSubscription(subscription);
|
|
1915
1897
|
return this.engine.deleteOrphanSubscription(subscription);
|
|
1916
1898
|
}
|
|
1917
1899
|
subscription = session.getSubscription(subscriptionId);
|
|
1918
1900
|
if (subscription) {
|
|
1919
|
-
|
|
1901
|
+
await this._beforeDeleteSubscription(subscription);
|
|
1920
1902
|
}
|
|
1921
1903
|
return session.deleteSubscription(subscriptionId);
|
|
1922
|
-
})
|
|
1904
|
+
});
|
|
1923
1905
|
}
|
|
1924
1906
|
_on_TransferSubscriptionsRequest(message, channel) {
|
|
1925
1907
|
//
|
|
@@ -1935,14 +1917,14 @@ class OPCUAServer extends base_server_1.OPCUABaseServer {
|
|
|
1935
1917
|
const engine = this.engine;
|
|
1936
1918
|
const request = message.request;
|
|
1937
1919
|
(0, node_opcua_assert_1.assert)(request instanceof node_opcua_service_subscription_1.TransferSubscriptionsRequest);
|
|
1938
|
-
this._apply_on_SubscriptionIds(node_opcua_service_subscription_1.TransferSubscriptionsResponse, message, channel, (session, subscriptionId) =>
|
|
1920
|
+
this._apply_on_SubscriptionIds(node_opcua_service_subscription_1.TransferSubscriptionsResponse, message, channel, async (session, subscriptionId) => await engine.transferSubscription(session, subscriptionId, request.sendInitialValues));
|
|
1939
1921
|
}
|
|
1940
1922
|
_on_CreateMonitoredItemsRequest(message, channel) {
|
|
1941
1923
|
const engine = this.engine;
|
|
1942
1924
|
const addressSpace = engine.addressSpace;
|
|
1943
1925
|
const request = message.request;
|
|
1944
1926
|
(0, node_opcua_assert_1.assert)(request instanceof node_opcua_service_subscription_1.CreateMonitoredItemsRequest);
|
|
1945
|
-
this._apply_on_Subscription(node_opcua_service_subscription_1.CreateMonitoredItemsResponse, message, channel, (session, subscription, sendResponse, sendError) =>
|
|
1927
|
+
this._apply_on_Subscription(node_opcua_service_subscription_1.CreateMonitoredItemsResponse, message, channel, async (session, subscription, sendResponse, sendError) => {
|
|
1946
1928
|
const timestampsToReturn = request.timestampsToReturn;
|
|
1947
1929
|
if (timestampsToReturn === node_opcua_service_read_1.TimestampsToReturn.Invalid) {
|
|
1948
1930
|
return sendError(node_opcua_status_code_1.StatusCodes.BadTimestampsToReturnInvalid);
|
|
@@ -1958,15 +1940,15 @@ class OPCUAServer extends base_server_1.OPCUABaseServer {
|
|
|
1958
1940
|
const options = this.options;
|
|
1959
1941
|
let results = [];
|
|
1960
1942
|
if (options.onCreateMonitoredItem) {
|
|
1961
|
-
const resultsPromise = request.itemsToCreate.map((monitoredItemCreateRequest) =>
|
|
1943
|
+
const resultsPromise = request.itemsToCreate.map(async (monitoredItemCreateRequest) => {
|
|
1962
1944
|
const { monitoredItem, createResult } = subscription.preCreateMonitoredItem(addressSpace, timestampsToReturn, monitoredItemCreateRequest);
|
|
1963
1945
|
if (monitoredItem) {
|
|
1964
|
-
|
|
1946
|
+
await options.onCreateMonitoredItem(subscription, monitoredItem);
|
|
1965
1947
|
subscription.postCreateMonitoredItem(monitoredItem, monitoredItemCreateRequest, createResult);
|
|
1966
1948
|
}
|
|
1967
1949
|
return createResult;
|
|
1968
|
-
})
|
|
1969
|
-
results =
|
|
1950
|
+
});
|
|
1951
|
+
results = await Promise.all(resultsPromise);
|
|
1970
1952
|
}
|
|
1971
1953
|
else {
|
|
1972
1954
|
results = request.itemsToCreate.map((monitoredItemCreateRequest) => {
|
|
@@ -1983,12 +1965,12 @@ class OPCUAServer extends base_server_1.OPCUABaseServer {
|
|
|
1983
1965
|
// ,diagnosticInfos: []
|
|
1984
1966
|
});
|
|
1985
1967
|
sendResponse(response);
|
|
1986
|
-
})
|
|
1968
|
+
});
|
|
1987
1969
|
}
|
|
1988
1970
|
_on_ModifySubscriptionRequest(message, channel) {
|
|
1989
1971
|
const request = message.request;
|
|
1990
1972
|
(0, node_opcua_assert_1.assert)(request instanceof node_opcua_service_subscription_1.ModifySubscriptionRequest);
|
|
1991
|
-
this._apply_on_Subscription(node_opcua_service_subscription_1.ModifySubscriptionResponse, message, channel, (session, subscription, sendResponse, sendError) =>
|
|
1973
|
+
this._apply_on_Subscription(node_opcua_service_subscription_1.ModifySubscriptionResponse, message, channel, async (session, subscription, sendResponse, sendError) => {
|
|
1992
1974
|
subscription.modify(request);
|
|
1993
1975
|
const response = new node_opcua_service_subscription_1.ModifySubscriptionResponse({
|
|
1994
1976
|
revisedLifetimeCount: subscription.lifeTimeCount,
|
|
@@ -1996,12 +1978,12 @@ class OPCUAServer extends base_server_1.OPCUABaseServer {
|
|
|
1996
1978
|
revisedPublishingInterval: subscription.publishingInterval
|
|
1997
1979
|
});
|
|
1998
1980
|
sendResponse(response);
|
|
1999
|
-
})
|
|
1981
|
+
});
|
|
2000
1982
|
}
|
|
2001
1983
|
_on_ModifyMonitoredItemsRequest(message, channel) {
|
|
2002
1984
|
const request = message.request;
|
|
2003
1985
|
(0, node_opcua_assert_1.assert)(request instanceof node_opcua_service_subscription_1.ModifyMonitoredItemsRequest);
|
|
2004
|
-
this._apply_on_Subscription(node_opcua_service_subscription_1.ModifyMonitoredItemsResponse, message, channel, (session, subscription, sendResponse, sendError) =>
|
|
1986
|
+
this._apply_on_Subscription(node_opcua_service_subscription_1.ModifyMonitoredItemsResponse, message, channel, async (session, subscription, sendResponse, sendError) => {
|
|
2005
1987
|
const timestampsToReturn = request.timestampsToReturn;
|
|
2006
1988
|
if (timestampsToReturn === node_opcua_service_read_1.TimestampsToReturn.Invalid) {
|
|
2007
1989
|
return sendError(node_opcua_status_code_1.StatusCodes.BadTimestampsToReturnInvalid);
|
|
@@ -2033,7 +2015,7 @@ class OPCUAServer extends base_server_1.OPCUABaseServer {
|
|
|
2033
2015
|
results
|
|
2034
2016
|
});
|
|
2035
2017
|
sendResponse(response);
|
|
2036
|
-
})
|
|
2018
|
+
});
|
|
2037
2019
|
}
|
|
2038
2020
|
_on_PublishRequest(message, channel) {
|
|
2039
2021
|
const request = message.request;
|
|
@@ -2050,14 +2032,14 @@ class OPCUAServer extends base_server_1.OPCUABaseServer {
|
|
|
2050
2032
|
const request = message.request;
|
|
2051
2033
|
(0, node_opcua_assert_1.assert)(request instanceof node_opcua_service_subscription_1.SetPublishingModeRequest);
|
|
2052
2034
|
const publishingEnabled = request.publishingEnabled;
|
|
2053
|
-
this._apply_on_Subscriptions(node_opcua_service_subscription_1.SetPublishingModeResponse, message, channel, (session, subscription) =>
|
|
2035
|
+
this._apply_on_Subscriptions(node_opcua_service_subscription_1.SetPublishingModeResponse, message, channel, async (session, subscription) => {
|
|
2054
2036
|
return subscription.setPublishingMode(publishingEnabled);
|
|
2055
|
-
})
|
|
2037
|
+
});
|
|
2056
2038
|
}
|
|
2057
2039
|
_on_DeleteMonitoredItemsRequest(message, channel) {
|
|
2058
2040
|
const request = message.request;
|
|
2059
2041
|
(0, node_opcua_assert_1.assert)(request instanceof node_opcua_service_subscription_1.DeleteMonitoredItemsRequest);
|
|
2060
|
-
this._apply_on_Subscription(node_opcua_service_subscription_1.DeleteMonitoredItemsResponse, message, channel, (session, subscription, sendResponse, sendError) =>
|
|
2042
|
+
this._apply_on_Subscription(node_opcua_service_subscription_1.DeleteMonitoredItemsResponse, message, channel, async (session, subscription, sendResponse, sendError) => {
|
|
2061
2043
|
/* istanbul ignore next */
|
|
2062
2044
|
if (!request.monitoredItemIds || request.monitoredItemIds.length === 0) {
|
|
2063
2045
|
return sendError(node_opcua_status_code_1.StatusCodes.BadNothingToDo);
|
|
@@ -2068,17 +2050,17 @@ class OPCUAServer extends base_server_1.OPCUABaseServer {
|
|
|
2068
2050
|
return sendError(node_opcua_status_code_1.StatusCodes.BadTooManyOperations);
|
|
2069
2051
|
}
|
|
2070
2052
|
}
|
|
2071
|
-
const resultsPromises = request.monitoredItemIds.map((monitoredItemId) =>
|
|
2053
|
+
const resultsPromises = request.monitoredItemIds.map(async (monitoredItemId) => {
|
|
2072
2054
|
if (this.options.onDeleteMonitoredItem) {
|
|
2073
2055
|
const monitoredItem = subscription.getMonitoredItem(monitoredItemId);
|
|
2074
2056
|
if (monitoredItem) {
|
|
2075
|
-
|
|
2057
|
+
await this.options.onDeleteMonitoredItem(subscription, monitoredItem);
|
|
2076
2058
|
}
|
|
2077
2059
|
}
|
|
2078
2060
|
return subscription.removeMonitoredItem(monitoredItemId);
|
|
2079
|
-
})
|
|
2061
|
+
});
|
|
2080
2062
|
try {
|
|
2081
|
-
const results =
|
|
2063
|
+
const results = await Promise.all(resultsPromises);
|
|
2082
2064
|
const response = new node_opcua_service_subscription_1.DeleteMonitoredItemsResponse({
|
|
2083
2065
|
diagnosticInfos: undefined,
|
|
2084
2066
|
results
|
|
@@ -2089,12 +2071,12 @@ class OPCUAServer extends base_server_1.OPCUABaseServer {
|
|
|
2089
2071
|
warningLog(err);
|
|
2090
2072
|
return sendError(node_opcua_status_code_1.StatusCodes.BadInternalError);
|
|
2091
2073
|
}
|
|
2092
|
-
})
|
|
2074
|
+
});
|
|
2093
2075
|
}
|
|
2094
2076
|
_on_SetTriggeringRequest(message, channel) {
|
|
2095
2077
|
const request = message.request;
|
|
2096
2078
|
(0, node_opcua_assert_1.assert)(request instanceof node_opcua_service_subscription_1.SetTriggeringRequest);
|
|
2097
|
-
this._apply_on_Subscription(node_opcua_service_subscription_1.SetTriggeringResponse, message, channel, (session, subscription, sendResponse, sendError) =>
|
|
2079
|
+
this._apply_on_Subscription(node_opcua_service_subscription_1.SetTriggeringResponse, message, channel, async (session, subscription, sendResponse, sendError) => {
|
|
2098
2080
|
/* */
|
|
2099
2081
|
const { triggeringItemId, linksToAdd, linksToRemove } = request;
|
|
2100
2082
|
/**
|
|
@@ -2125,20 +2107,18 @@ class OPCUAServer extends base_server_1.OPCUABaseServer {
|
|
|
2125
2107
|
});
|
|
2126
2108
|
sendResponse(response);
|
|
2127
2109
|
}
|
|
2128
|
-
}));
|
|
2129
|
-
}
|
|
2130
|
-
_beforeDeleteSubscription(subscription) {
|
|
2131
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
2132
|
-
if (!this.options.onDeleteMonitoredItem) {
|
|
2133
|
-
return;
|
|
2134
|
-
}
|
|
2135
|
-
yield subscription.applyOnMonitoredItem(this.options.onDeleteMonitoredItem.bind(null, subscription));
|
|
2136
2110
|
});
|
|
2137
2111
|
}
|
|
2112
|
+
async _beforeDeleteSubscription(subscription) {
|
|
2113
|
+
if (!this.options.onDeleteMonitoredItem) {
|
|
2114
|
+
return;
|
|
2115
|
+
}
|
|
2116
|
+
await subscription.applyOnMonitoredItem(this.options.onDeleteMonitoredItem.bind(null, subscription));
|
|
2117
|
+
}
|
|
2138
2118
|
_on_RepublishRequest(message, channel) {
|
|
2139
2119
|
const request = message.request;
|
|
2140
2120
|
(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, (session, subscription, sendResponse, sendError) =>
|
|
2121
|
+
this._apply_on_Subscription(node_opcua_service_subscription_1.RepublishResponse, message, channel, async (session, subscription, sendResponse, sendError) => {
|
|
2142
2122
|
// update diagnostic counter
|
|
2143
2123
|
subscription.subscriptionDiagnostics.republishRequestCount += 1;
|
|
2144
2124
|
subscription.subscriptionDiagnostics.republishMessageRequestCount += 1;
|
|
@@ -2156,7 +2136,7 @@ class OPCUAServer extends base_server_1.OPCUABaseServer {
|
|
|
2156
2136
|
// update diagnostic counter
|
|
2157
2137
|
subscription.subscriptionDiagnostics.republishMessageCount += 1;
|
|
2158
2138
|
sendResponse(response);
|
|
2159
|
-
})
|
|
2139
|
+
});
|
|
2160
2140
|
}
|
|
2161
2141
|
// Bad_NothingToDo
|
|
2162
2142
|
// Bad_TooManyOperations
|
|
@@ -2165,7 +2145,7 @@ class OPCUAServer extends base_server_1.OPCUABaseServer {
|
|
|
2165
2145
|
_on_SetMonitoringModeRequest(message, channel) {
|
|
2166
2146
|
const request = message.request;
|
|
2167
2147
|
(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, (session, subscription, sendResponse, sendError) =>
|
|
2148
|
+
this._apply_on_Subscription(node_opcua_service_subscription_1.SetMonitoringModeResponse, message, channel, async (session, subscription, sendResponse, sendError) => {
|
|
2169
2149
|
/* istanbul ignore next */
|
|
2170
2150
|
if (!request.monitoredItemIds || request.monitoredItemIds.length === 0) {
|
|
2171
2151
|
return sendError(node_opcua_status_code_1.StatusCodes.BadNothingToDo);
|
|
@@ -2192,13 +2172,13 @@ class OPCUAServer extends base_server_1.OPCUABaseServer {
|
|
|
2192
2172
|
results
|
|
2193
2173
|
});
|
|
2194
2174
|
sendResponse(response);
|
|
2195
|
-
})
|
|
2175
|
+
});
|
|
2196
2176
|
}
|
|
2197
2177
|
// _on_TranslateBrowsePathsToNodeIds service
|
|
2198
2178
|
_on_TranslateBrowsePathsToNodeIdsRequest(message, channel) {
|
|
2199
2179
|
const request = message.request;
|
|
2200
2180
|
(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, (session, sendResponse, sendError) =>
|
|
2181
|
+
this._apply_on_SessionObject(node_opcua_service_translate_browse_path_1.TranslateBrowsePathsToNodeIdsResponse, message, channel, async (session, sendResponse, sendError) => {
|
|
2202
2182
|
if (!request.browsePaths || request.browsePaths.length === 0) {
|
|
2203
2183
|
return sendError(node_opcua_status_code_1.StatusCodes.BadNothingToDo);
|
|
2204
2184
|
}
|
|
@@ -2220,7 +2200,7 @@ class OPCUAServer extends base_server_1.OPCUABaseServer {
|
|
|
2220
2200
|
.catch((err) => {
|
|
2221
2201
|
sendError(node_opcua_status_code_1.StatusCodes.BadInternalError);
|
|
2222
2202
|
});
|
|
2223
|
-
})
|
|
2203
|
+
});
|
|
2224
2204
|
}
|
|
2225
2205
|
// Call Service Result Codes
|
|
2226
2206
|
// Symbolic Id Description
|
|
@@ -2384,14 +2364,9 @@ class OPCUAServer extends base_server_1.OPCUABaseServer {
|
|
|
2384
2364
|
});
|
|
2385
2365
|
return endPoint;
|
|
2386
2366
|
}
|
|
2387
|
-
initializeCM() {
|
|
2388
|
-
|
|
2389
|
-
|
|
2390
|
-
});
|
|
2391
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
2392
|
-
yield _super.initializeCM.call(this);
|
|
2393
|
-
yield this.userCertificateManager.initialize();
|
|
2394
|
-
});
|
|
2367
|
+
async initializeCM() {
|
|
2368
|
+
await super.initializeCM();
|
|
2369
|
+
await this.userCertificateManager.initialize();
|
|
2395
2370
|
}
|
|
2396
2371
|
}
|
|
2397
2372
|
exports.OPCUAServer = OPCUAServer;
|