node-opcua-server 2.73.1 → 2.76.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (72) hide show
  1. package/LICENSE +3 -1
  2. package/dist/base_server.d.ts +110 -110
  3. package/dist/base_server.js +473 -473
  4. package/dist/factory.d.ts +12 -12
  5. package/dist/factory.js +23 -23
  6. package/dist/filter/check_where_clause_on_address_space.d.ts +3 -0
  7. package/dist/filter/check_where_clause_on_address_space.js +23 -0
  8. package/dist/filter/check_where_clause_on_address_space.js.map +1 -0
  9. package/dist/filter/extract_event_fields.d.ts +10 -0
  10. package/dist/filter/extract_event_fields.js +18 -0
  11. package/dist/filter/extract_event_fields.js.map +1 -0
  12. package/dist/helper.d.ts +10 -10
  13. package/dist/helper.js +75 -75
  14. package/dist/history_server_capabilities.d.ts +35 -35
  15. package/dist/history_server_capabilities.js +43 -43
  16. package/dist/i_channel_data.d.ts +13 -13
  17. package/dist/i_channel_data.js +2 -2
  18. package/dist/i_register_server_manager.d.ts +16 -16
  19. package/dist/i_register_server_manager.js +2 -2
  20. package/dist/i_server_side_publish_engine.d.ts +36 -36
  21. package/dist/i_server_side_publish_engine.js +49 -49
  22. package/dist/i_socket_data.d.ts +11 -11
  23. package/dist/i_socket_data.js +2 -2
  24. package/dist/index.d.ts +16 -16
  25. package/dist/index.js +32 -32
  26. package/dist/monitored_item.d.ts +177 -177
  27. package/dist/monitored_item.js +1001 -999
  28. package/dist/monitored_item.js.map +1 -1
  29. package/dist/node_sampler.d.ts +3 -3
  30. package/dist/node_sampler.js +75 -75
  31. package/dist/opcua_server.d.ts +747 -650
  32. package/dist/opcua_server.js +2431 -2394
  33. package/dist/opcua_server.js.map +1 -1
  34. package/dist/queue.d.ts +11 -11
  35. package/dist/queue.js +71 -71
  36. package/dist/register_server_manager.d.ts +96 -96
  37. package/dist/register_server_manager.js +584 -584
  38. package/dist/register_server_manager_hidden.d.ts +17 -17
  39. package/dist/register_server_manager_hidden.js +27 -27
  40. package/dist/register_server_manager_mdns_only.d.ts +22 -22
  41. package/dist/register_server_manager_mdns_only.js +55 -55
  42. package/dist/server_capabilities.d.ts +148 -148
  43. package/dist/server_capabilities.js +92 -92
  44. package/dist/server_end_point.d.ts +183 -183
  45. package/dist/server_end_point.js +817 -817
  46. package/dist/server_engine.d.ts +317 -317
  47. package/dist/server_engine.js +1716 -1716
  48. package/dist/server_publish_engine.d.ts +113 -112
  49. package/dist/server_publish_engine.js +541 -535
  50. package/dist/server_publish_engine.js.map +1 -1
  51. package/dist/server_publish_engine_for_orphan_subscriptions.d.ts +16 -16
  52. package/dist/server_publish_engine_for_orphan_subscriptions.js +51 -51
  53. package/dist/server_session.d.ts +182 -182
  54. package/dist/server_session.js +739 -739
  55. package/dist/server_subscription.d.ts +421 -421
  56. package/dist/server_subscription.js +1346 -1345
  57. package/dist/server_subscription.js.map +1 -1
  58. package/dist/sessions_compatible_for_transfer.d.ts +2 -2
  59. package/dist/sessions_compatible_for_transfer.js +39 -39
  60. package/dist/user_manager.d.ts +32 -32
  61. package/dist/user_manager.js +74 -74
  62. package/dist/user_manager_ua.d.ts +3 -3
  63. package/dist/user_manager_ua.js +39 -39
  64. package/dist/validate_filter.d.ts +5 -5
  65. package/dist/validate_filter.js +60 -60
  66. package/package.json +50 -51
  67. package/source/filter/check_where_clause_on_address_space.ts +29 -0
  68. package/source/filter/extract_event_fields.ts +21 -0
  69. package/source/monitored_item.ts +5 -11
  70. package/source/opcua_server.ts +175 -36
  71. package/source/server_publish_engine.ts +24 -19
  72. package/source/server_subscription.ts +11 -10
@@ -1,3 +1,4 @@
1
+ /* eslint-disable complexity */
1
2
  /**
2
3
  * @module node-opcua-server
3
4
  */
@@ -38,7 +39,8 @@ import {
38
39
  ISessionContext,
39
40
  UAView,
40
41
  EventTypeLike,
41
- UAObjectType
42
+ UAObjectType,
43
+ PseudoVariantStringPredefined
42
44
  } from "node-opcua-address-space";
43
45
  import { getDefaultCertificateManager, OPCUACertificateManager } from "node-opcua-certificate-manager";
44
46
  import { ServerState } from "node-opcua-common";
@@ -145,13 +147,16 @@ import {
145
147
  BuildInfoOptions,
146
148
  MonitoredItemCreateResult,
147
149
  IssuedIdentityToken,
148
- BrowseResultOptions
150
+ BrowseResultOptions,
151
+ ServiceFault,
152
+ ServerDiagnosticsSummaryDataType
149
153
  } from "node-opcua-types";
150
154
  import { DataType } from "node-opcua-variant";
151
155
  import { VariantArrayType } from "node-opcua-variant";
152
156
  import { matchUri } from "node-opcua-utils";
153
157
 
154
158
  import { UAString } from "node-opcua-basic-types";
159
+ import { ObjectIds, ObjectTypeIds } from "node-opcua-constants";
155
160
  import { OPCUABaseServer, OPCUABaseServerOptions } from "./base_server";
156
161
  import { Factory } from "./factory";
157
162
  import { IRegisterServerManager } from "./i_register_server_manager";
@@ -184,7 +189,7 @@ const warningLog = make_warningLog(__filename);
184
189
  const default_maxConnectionsPerEndpoint = 10;
185
190
 
186
191
  function g_sendError(channel: ServerSecureChannelLayer, message: Message, ResponseClass: any, statusCode: StatusCode): void {
187
- const response = new ResponseClass({
192
+ const response = new ServiceFault({
188
193
  responseHeader: { serviceResult: statusCode }
189
194
  });
190
195
  return channel.send_response("MSG", response, message);
@@ -261,11 +266,8 @@ async function _attempt_to_close_some_old_unactivated_session(server: OPCUAServe
261
266
 
262
267
  function getRequiredEndpointInfo(endpoint: EndpointDescription) {
263
268
  assert(endpoint instanceof EndpointDescription);
264
- // It is recommended that Servers only include the server.applicationUri, endpointUrl, securityMode,
265
- // securityPolicyUri, userIdentityTokens, transportProfileUri and securityLevel with all
266
- // other parameters set to null. Only the recommended parameters shall be verified by
267
- // the client.
268
-
269
+ // https://reference.opcfoundation.org/v104/Core/docs/Part4/5.6.2/
270
+ // https://reference.opcfoundation.org/v105/Core/docs/Part4/5.6.2/
269
271
  const e = new EndpointDescription({
270
272
  endpointUrl: endpoint.endpointUrl,
271
273
  securityLevel: endpoint.securityLevel,
@@ -274,14 +276,13 @@ function getRequiredEndpointInfo(endpoint: EndpointDescription) {
274
276
  server: {
275
277
  applicationUri: endpoint.server.applicationUri,
276
278
  applicationType: endpoint.server.applicationType,
277
- applicationName: endpoint.server.applicationName
278
- // ... to be continued after verifying what fields are actually needed
279
+ applicationName: endpoint.server.applicationName,
280
+ productUri: endpoint.server.productUri
279
281
  },
280
282
  transportProfileUri: endpoint.transportProfileUri,
281
283
  userIdentityTokens: endpoint.userIdentityTokens
282
284
  });
283
285
  // reduce even further by explicitly setting unwanted members to null
284
- e.server.productUri = null;
285
286
  e.server.applicationName = null as any;
286
287
  // xx e.server.applicationType = null as any;
287
288
  e.server.gatewayServerUri = null;
@@ -298,10 +299,8 @@ function getRequiredEndpointInfo(endpoint: EndpointDescription) {
298
299
  function _serverEndpointsForCreateSessionResponse(server: OPCUAServer, endpointUrl: string | null, serverUri: string | null) {
299
300
  serverUri = null; // unused then
300
301
 
301
- // The Server shall return a set of EndpointDescriptions available for the serverUri specified in the request.
302
- // It is recommended that Servers only include the endpointUrl, securityMode,
303
- // securityPolicyUri, userIdentityTokens, transportProfileUri and securityLevel with all other parameters
304
- // set to null. Only the recommended parameters shall be verified by the client.
302
+ // https://reference.opcfoundation.org/v104/Core/docs/Part4/5.6.2/
303
+ // https://reference.opcfoundation.org/v105/Core/docs/Part4/5.6.2/
305
304
  return server
306
305
  ._get_endpoints(endpointUrl)
307
306
  .filter((e) => !(e as any).restricted) // remove restricted endpoints
@@ -1355,6 +1354,19 @@ export class OPCUAServer extends OPCUABaseServer {
1355
1354
  }
1356
1355
  }
1357
1356
 
1357
+ public raiseEvent(eventType: "AuditSessionEventType", options: RaiseEventAuditSessionEventData): void;
1358
+ public raiseEvent(eventType: "AuditCreateSessionEventType", options: RaiseEventAuditCreateSessionEventData): void;
1359
+ public raiseEvent(eventType: "AuditActivateSessionEventType", options: RaiseEventAuditActivateSessionEventData): void;
1360
+ public raiseEvent(eventType: "AuditCreateSessionEventType", options: RaiseEventData): void;
1361
+ public raiseEvent(eventType: "AuditConditionCommentEventType", options: RaiseEventAuditConditionCommentEventData): void;
1362
+ public raiseEvent(eventType: "AuditUrlMismatchEventType", options: RaiseEventAuditUrlMismatchEventTypeData): void;
1363
+ public raiseEvent(eventType: "TransitionEventType", options: RaiseEventTransitionEventData): void;
1364
+ public raiseEvent(eventType: "AuditCertificateInvalidEventType", options: RaiseAuditCertificateInvalidEventData): void;
1365
+ public raiseEvent(eventType: "AuditCertificateExpiredEventType", options: RaiseAuditCertificateExpiredEventData): void;
1366
+ public raiseEvent(eventType: "AuditCertificateUntrustedEventType", options: RaiseAuditCertificateUntrustedEventData): void;
1367
+ public raiseEvent(eventType: "AuditCertificateRevokedEventType", options: RaiseAuditCertificateRevokedEventData): void;
1368
+ public raiseEvent(eventType: "AuditCertificateMismatchEventType", options: RaiseAuditCertificateMismatchEventData): void;
1369
+
1358
1370
  public raiseEvent(eventType: EventTypeLike | UAObjectType, options: RaiseEventData): void {
1359
1371
  /* istanbul ignore next */
1360
1372
  if (!this.engine.addressSpace) {
@@ -1495,6 +1507,8 @@ export class OPCUAServer extends OPCUABaseServer {
1495
1507
  }
1496
1508
 
1497
1509
  if (!userTokenSignature || !userTokenSignature.signature) {
1510
+ this.raiseEvent("AuditCreateSessionEventType", {});
1511
+
1498
1512
  return callback(null, StatusCodes.BadUserSignatureInvalid);
1499
1513
  }
1500
1514
 
@@ -1524,6 +1538,45 @@ export class OPCUAServer extends OPCUABaseServer {
1524
1538
  if (err) {
1525
1539
  return callback(err);
1526
1540
  }
1541
+ if (this.isAuditing) {
1542
+ switch (certificateStatus) {
1543
+ case StatusCodes.Good:
1544
+ break;
1545
+ case StatusCodes.BadCertificateUntrusted:
1546
+ this.raiseEvent("AuditCertificateUntrustedEventType", {
1547
+ certificate: { dataType: DataType.ByteString, value: certificate },
1548
+ sourceName: { dataType: DataType.String, value: "Security/Certificate" }
1549
+ });
1550
+ break;
1551
+ case StatusCodes.BadCertificateTimeInvalid:
1552
+ case StatusCodes.BadCertificateIssuerTimeInvalid:
1553
+ this.raiseEvent("AuditCertificateExpiredEventType", {
1554
+ certificate: { dataType: DataType.ByteString, value: certificate },
1555
+ sourceName: { dataType: DataType.String, value: "Security/Certificate" },
1556
+ comment: { dataType: DataType.String, value: certificateStatus.toString() }
1557
+ });
1558
+ break;
1559
+ case StatusCodes.BadCertificateRevoked:
1560
+ case StatusCodes.BadCertificateRevocationUnknown:
1561
+ case StatusCodes.BadCertificateIssuerRevocationUnknown:
1562
+ this.raiseEvent("AuditCertificateRevokedEventType", {
1563
+ certificate: { dataType: DataType.ByteString, value: certificate },
1564
+ sourceName: { dataType: DataType.String, value: "Security/Certificate" },
1565
+ comment: { dataType: DataType.String, value: certificateStatus.toString() }
1566
+ });
1567
+ break;
1568
+ case StatusCodes.BadCertificateIssuerUseNotAllowed:
1569
+ case StatusCodes.BadCertificateUseNotAllowed:
1570
+ case StatusCodes.BadSecurityChecksFailed:
1571
+ this.raiseEvent("AuditCertificateMismatchEventType", {
1572
+ certificate: { dataType: DataType.ByteString, value: certificate },
1573
+ sourceName: { dataType: DataType.String, value: "Security/Certificate" },
1574
+ comment: { dataType: DataType.String, value: certificateStatus.toString() }
1575
+ });
1576
+ break;
1577
+
1578
+ }
1579
+ }
1527
1580
  if (
1528
1581
  StatusCodes.BadCertificateUntrusted === certificateStatus ||
1529
1582
  StatusCodes.BadCertificateTimeInvalid === certificateStatus ||
@@ -1537,6 +1590,7 @@ export class OPCUAServer extends OPCUABaseServer {
1537
1590
  StatusCodes.Good !== certificateStatus
1538
1591
  ) {
1539
1592
  debugLog("isValidX509IdentityToken => certificateStatus = ", certificateStatus?.toString());
1593
+
1540
1594
  return callback(null, StatusCodes.BadIdentityTokenRejected);
1541
1595
  }
1542
1596
  if (StatusCodes.Good !== certificateStatus) {
@@ -2233,7 +2287,7 @@ export class OPCUAServer extends OPCUABaseServer {
2233
2287
 
2234
2288
  function sendResponse(response1: Response) {
2235
2289
  try {
2236
- assert(response1 instanceof ResponseClass);
2290
+ assert(response1 instanceof ResponseClass || response1 instanceof ServiceFault);
2237
2291
  if (message.session) {
2238
2292
  const counterName = ResponseClass.name.replace("Response", "");
2239
2293
  message.session.incrementRequestTotalCounter(counterName);
@@ -3071,7 +3125,7 @@ export class OPCUAServer extends OPCUABaseServer {
3071
3125
  (session: ServerSession, sendResponse: (response: Response) => void, sendError: (statusCode: StatusCode) => void) => {
3072
3126
  assert(session);
3073
3127
  assert(session.publishEngine); // server.publishEngine doesn't exists, OPCUAServer has probably shut down already
3074
- session.publishEngine._on_PublishRequest(request, (request1: PublishRequest, response: PublishResponse) => {
3128
+ session.publishEngine._on_PublishRequest(request, (_request1, response) => {
3075
3129
  sendResponse(response);
3076
3130
  });
3077
3131
  }
@@ -3180,16 +3234,20 @@ export class OPCUAServer extends OPCUABaseServer {
3180
3234
  linksToAdd,
3181
3235
  linksToRemove
3182
3236
  );
3183
- const response = new SetTriggeringResponse({
3184
- responseHeader: { serviceResult: statusCode },
3185
-
3186
- addResults,
3187
- removeResults,
3188
- addDiagnosticInfos: null,
3189
- removeDiagnosticInfos: null
3190
- });
3237
+ if (statusCode !== StatusCodes.Good) {
3238
+ const response = new ServiceFault({ responseHeader: { serviceResult: statusCode } });
3239
+ sendResponse(response);
3240
+ } else {
3241
+ const response = new SetTriggeringResponse({
3242
+ responseHeader: { serviceResult: statusCode },
3191
3243
 
3192
- sendResponse(response);
3244
+ addResults,
3245
+ removeResults,
3246
+ addDiagnosticInfos: null,
3247
+ removeDiagnosticInfos: null
3248
+ });
3249
+ sendResponse(response);
3250
+ }
3193
3251
  }
3194
3252
  );
3195
3253
  }
@@ -3390,11 +3448,8 @@ export class OPCUAServer extends OPCUABaseServer {
3390
3448
  message,
3391
3449
  channel,
3392
3450
  (session: ServerSession, sendResponse: (response: Response) => void, sendError: (statusCode: StatusCode) => void) => {
3393
- let response;
3394
-
3395
3451
  if (!request.nodesToRegister || request.nodesToRegister.length === 0) {
3396
- response = new RegisterNodesResponse({ responseHeader: { serviceResult: StatusCodes.BadNothingToDo } });
3397
- return sendResponse(response);
3452
+ return sendError(StatusCodes.BadNothingToDo);
3398
3453
  }
3399
3454
  if (this.engine.serverCapabilities.operationLimits.maxNodesPerRegisterNodes > 0) {
3400
3455
  if (request.nodesToRegister.length > this.engine.serverCapabilities.operationLimits.maxNodesPerRegisterNodes) {
@@ -3410,7 +3465,7 @@ export class OPCUAServer extends OPCUABaseServer {
3410
3465
  // NodeId from the request.
3411
3466
  const registeredNodeIds = request.nodesToRegister.map((nodeId) => session.registerNode(nodeId));
3412
3467
 
3413
- response = new RegisterNodesResponse({
3468
+ const response = new RegisterNodesResponse({
3414
3469
  registeredNodeIds
3415
3470
  });
3416
3471
  sendResponse(response);
@@ -3427,13 +3482,10 @@ export class OPCUAServer extends OPCUABaseServer {
3427
3482
  message,
3428
3483
  channel,
3429
3484
  (session: ServerSession, sendResponse: (response: Response) => void, sendError: (statusCode: StatusCode) => void) => {
3430
- let response;
3431
-
3432
3485
  request.nodesToUnregister = request.nodesToUnregister || [];
3433
3486
 
3434
3487
  if (!request.nodesToUnregister || request.nodesToUnregister.length === 0) {
3435
- response = new UnregisterNodesResponse({ responseHeader: { serviceResult: StatusCodes.BadNothingToDo } });
3436
- return sendResponse(response);
3488
+ return sendError(StatusCodes.BadNothingToDo);
3437
3489
  }
3438
3490
 
3439
3491
  if (this.engine.serverCapabilities.operationLimits.maxNodesPerRegisterNodes > 0) {
@@ -3446,7 +3498,7 @@ export class OPCUAServer extends OPCUABaseServer {
3446
3498
 
3447
3499
  request.nodesToUnregister.map((nodeId: NodeId) => session.unRegisterNode(nodeId));
3448
3500
 
3449
- response = new UnregisterNodesResponse({});
3501
+ const response = new UnregisterNodesResponse({});
3450
3502
  sendResponse(response);
3451
3503
  }
3452
3504
  );
@@ -3643,6 +3695,87 @@ export interface RaiseEventTransitionEventData extends RaiseEventData {}
3643
3695
  export interface RaiseEventAuditUrlMismatchEventTypeData extends RaiseEventData {
3644
3696
  endpointUrl: PseudoVariantString;
3645
3697
  }
3698
+
3699
+ /**
3700
+ * The SourceName for Events of this type shall be “Security/Certificate”.
3701
+ */
3702
+ export interface RaiseAuditCertificateEventData extends RaiseEventData {
3703
+ certificate: PseudoVariantByteString;
3704
+ sourceName: PseudoVariantStringPredefined<"Security/Certificate">;
3705
+ }
3706
+
3707
+ /**
3708
+ * This EventType inherits all Properties of the AuditCertificateEventType.
3709
+ * Either the InvalidHostname or InvalidUri shall be provided.
3710
+ */
3711
+ export interface RaiseAuditCertificateDataMismatchEventData extends RaiseAuditCertificateEventData {
3712
+ /**
3713
+ * InvalidHostname is the string that represents the host name passed in as part of the URL
3714
+ * that is found to be invalid. If the host name was not invalid it can be null.
3715
+ */
3716
+ invalidHostname: PseudoVariantString;
3717
+ /*
3718
+ * InvalidUri is the URI that was passed in and found to not match what is contained in
3719
+ * the certificate. If the URI was not invalid it can be null.
3720
+ */
3721
+ invalidUri: PseudoVariantString;
3722
+ }
3723
+ export interface RaiseAuditCertificateUntrustedEventData extends RaiseAuditCertificateEventData {}
3724
+ /**
3725
+ * This EventType inherits all Properties of the AuditCertificateEventType.
3726
+ *
3727
+ * The SourceName for Events of this type shall be “Security/Certificate”.
3728
+ *
3729
+ * The Message Variable shall include a description of why the certificate was expired
3730
+ * (i.e. time before start or time after end).
3731
+ *
3732
+ * There are no additional Properties defined for this EventType.
3733
+ *
3734
+ */
3735
+ export interface RaiseAuditCertificateExpiredEventData extends RaiseAuditCertificateEventData {}
3736
+ /**
3737
+ * This EventType inherits all Properties of the AuditCertificateEventType.
3738
+ *
3739
+ * The SourceName for Events of this type shall be “Security/Certificate”.
3740
+ *
3741
+ * The Message shall include a description of why the certificate is invalid.
3742
+ *
3743
+ * There are no additional Properties defined for this EventType.
3744
+ */
3745
+ export interface RaiseAuditCertificateInvalidEventData extends RaiseAuditCertificateEventData {}
3746
+ /**
3747
+ * This EventType inherits all Properties of the AuditCertificateEventType.
3748
+ *
3749
+ * The SourceName for Events of this type shall be “Security/Certificate”.
3750
+ *
3751
+ * The Message Variable shall include a description of why the certificate is not trusted.
3752
+ * If a trust chain is involved then the certificate that failed in the trust chain should be described.
3753
+ * There are no additional Properties defined for this EventType.
3754
+ */
3755
+ export interface RaiseAuditCertificateUntrustedEventData extends RaiseAuditCertificateEventData {}
3756
+ /**
3757
+ * This EventType inherits all Properties of the AuditCertificateEventType.
3758
+ *
3759
+ * The SourceName for Events of this type shall be “Security/Certificate”.
3760
+ *
3761
+ * The Message Variable shall include a description of why the certificate is revoked
3762
+ * (was the revocation list unavailable or was the certificate on the list).
3763
+ *
3764
+ * There are no additional Properties defined for this EventType.
3765
+ */
3766
+ export interface RaiseAuditCertificateRevokedEventData extends RaiseAuditCertificateEventData {
3767
+ sourceName: PseudoVariantStringPredefined<"Security/Certificate">;
3768
+ }
3769
+ /**
3770
+ * This EventType inherits all Properties of the AuditCertificateEventType.
3771
+ *
3772
+ * The SourceName for Events of this type shall be “Security/Certificate”.
3773
+ *
3774
+ * The Message Variable shall include a description of misuse of the certificate.
3775
+ *
3776
+ * There are no additional Properties defined for this EventType
3777
+ */
3778
+ export interface RaiseAuditCertificateMismatchEventData extends RaiseAuditCertificateEventData {}
3646
3779
  export interface OPCUAServer {
3647
3780
  /**
3648
3781
  * @internal
@@ -3662,6 +3795,12 @@ export interface OPCUAServer {
3662
3795
  raiseEvent(eventType: "AuditUrlMismatchEventType", options: RaiseEventAuditUrlMismatchEventTypeData): void;
3663
3796
 
3664
3797
  raiseEvent(eventType: "TransitionEventType", options: RaiseEventTransitionEventData): void;
3798
+
3799
+ raiseEvent(eventType: "AuditCertificateInvalidEventType", options: RaiseAuditCertificateInvalidEventData): void;
3800
+ raiseEvent(eventType: "AuditCertificateExpiredEventType", options: RaiseAuditCertificateExpiredEventData): void;
3801
+ raiseEvent(eventType: "AuditCertificateUntrustedEventType", options: RaiseAuditCertificateUntrustedEventData): void;
3802
+ raiseEvent(eventType: "AuditCertificateRevokedEventType", options: RaiseAuditCertificateRevokedEventData): void;
3803
+ raiseEvent(eventType: "AuditCertificateMismatchEventType", options: RaiseAuditCertificateMismatchEventData): void;
3665
3804
  }
3666
3805
 
3667
3806
  export interface OPCUAServer extends EventEmitter {
@@ -11,7 +11,7 @@ import { checkDebugFlag, make_debugLog } from "node-opcua-debug";
11
11
  import { ObjectRegistry } from "node-opcua-object-registry";
12
12
  import { StatusCode, StatusCodes } from "node-opcua-status-code";
13
13
 
14
- import { PublishRequest, PublishResponse, SubscriptionAcknowledgement } from "node-opcua-types";
14
+ import { PublishRequest, PublishResponse, ServiceFault, SubscriptionAcknowledgement } from "node-opcua-types";
15
15
  import { Subscription } from "./server_subscription";
16
16
  import { SubscriptionState } from "./server_subscription";
17
17
  import { IServerSidePublishEngine, INotifMsg, IClosedOrTransferredSubscription } from "./i_server_side_publish_engine";
@@ -36,7 +36,7 @@ interface PublishData {
36
36
  request: PublishRequest;
37
37
  serverTimeWhenReceived: number;
38
38
  results: StatusCode[];
39
- callback: (request: PublishRequest, response: PublishResponse) => void;
39
+ callback: (request: PublishRequest, response: PublishResponse | ServiceFault) => void;
40
40
  }
41
41
 
42
42
  function _assertValidPublishData(publishData: PublishData) {
@@ -137,7 +137,7 @@ export class ServerSidePublishEngine extends EventEmitter implements IServerSide
137
137
 
138
138
  const tmp = srcPublishEngine.detach_subscription(subscription);
139
139
  destPublishEngine.add_subscription(tmp);
140
-
140
+
141
141
  subscription.resetLifeTimeCounter();
142
142
  if (sendInitialValues) {
143
143
  /* A Boolean parameter with the following values:
@@ -327,11 +327,12 @@ export class ServerSidePublishEngine extends EventEmitter implements IServerSide
327
327
  public on_close_subscription(subscription: IClosedOrTransferredSubscription): void {
328
328
  doDebug && debugLog("ServerSidePublishEngine#on_close_subscription", subscription.id);
329
329
  if (subscription.hasPendingNotifications) {
330
- doDebug && debugLog(
331
- "ServerSidePublishEngine#on_close_subscription storing subscription",
332
- subscription.id,
333
- " to _closed_subscriptions because it has pending notification"
334
- );
330
+ doDebug &&
331
+ debugLog(
332
+ "ServerSidePublishEngine#on_close_subscription storing subscription",
333
+ subscription.id,
334
+ " to _closed_subscriptions because it has pending notification"
335
+ );
335
336
  this._closed_subscriptions.push(subscription);
336
337
  } else {
337
338
  doDebug && debugLog("ServerSidePublishEngine#on_close_subscription disposing subscription", subscription.id);
@@ -402,7 +403,7 @@ export class ServerSidePublishEngine extends EventEmitter implements IServerSide
402
403
  */
403
404
  public _on_PublishRequest(
404
405
  request: PublishRequest,
405
- callback?: (request1: PublishRequest, response: PublishResponse) => void
406
+ callback?: (request1: PublishRequest, response: PublishResponse| ServiceFault) => void
406
407
  ): void {
407
408
  callback = callback || dummy_function;
408
409
  assert(typeof callback === "function");
@@ -483,9 +484,10 @@ export class ServerSidePublishEngine extends EventEmitter implements IServerSide
483
484
  s.timeToKeepAlive +
484
485
  " m?=" +
485
486
  s.hasUncollectedMonitoredItemNotifications +
486
- " " +
487
+ " " +
487
488
  SubscriptionState[s.state] +
488
- " " + s.messageSent +
489
+ " " +
490
+ s.messageSent +
489
491
  "]"
490
492
  )
491
493
  .join(" \n")
@@ -508,7 +510,8 @@ export class ServerSidePublishEngine extends EventEmitter implements IServerSide
508
510
  }
509
511
  const starving_subscription = this._find_starving_subscription();
510
512
  if (starving_subscription) {
511
- doDebug && debugLog(chalk.bgWhite.red("feeding most late subscription subscriptionId = "), starving_subscription.id);
513
+ doDebug &&
514
+ debugLog(chalk.bgWhite.red("feeding most late subscription subscriptionId = "), starving_subscription.id);
512
515
  starving_subscription.process_subscription();
513
516
  }
514
517
  });
@@ -537,10 +540,10 @@ export class ServerSidePublishEngine extends EventEmitter implements IServerSide
537
540
 
538
541
  private _send_error_for_request(publishData: PublishData, statusCode: StatusCode): void {
539
542
  _assertValidPublishData(publishData);
540
- const publishResponse = new PublishResponse({
543
+ const response = new ServiceFault({
541
544
  responseHeader: { serviceResult: statusCode }
542
545
  });
543
- this._send_response_for_request(publishData, publishResponse);
546
+ this._send_response_for_request(publishData, response);
544
547
  }
545
548
 
546
549
  private _cancelPendingPublishRequest(statusCode: StatusCode): void {
@@ -629,7 +632,7 @@ export class ServerSidePublishEngine extends EventEmitter implements IServerSide
629
632
  assert(this.pendingPublishRequestCount > 0);
630
633
  assert(response.subscriptionId !== 0xffffff);
631
634
  const publishData = this._publish_request_queue.shift()!;
632
- this._send_response_for_request(publishData, response);
635
+ this._send_valid_response_for_request(publishData, response);
633
636
  }
634
637
 
635
638
  public _on_tick(): void {
@@ -654,15 +657,17 @@ export class ServerSidePublishEngine extends EventEmitter implements IServerSide
654
657
  this._send_error_for_request(publishData, StatusCodes.BadTimeout);
655
658
  }
656
659
  }
657
-
658
- public _send_response_for_request(publishData: PublishData, response: PublishResponse): void {
660
+ public _send_response_for_request(publishData: PublishData, response: PublishResponse | ServiceFault): void {
661
+ response.responseHeader.requestHandle = publishData.request.requestHeader.requestHandle;
662
+ publishData.callback(publishData.request, response);
663
+ }
664
+ public _send_valid_response_for_request(publishData: PublishData, response: PublishResponse): void {
659
665
  if (doDebug) {
660
666
  debugLog("_send_response_for_request ", response.toString());
661
667
  }
662
668
  _assertValidPublishData(publishData);
663
669
  // xx assert(response.responseHeader.requestHandle !== 0,"expecting a valid requestHandle");
664
670
  response.results = publishData.results;
665
- response.responseHeader.requestHandle = publishData.request.requestHeader.requestHandle;
666
- publishData.callback(publishData.request, response);
671
+ this._send_response_for_request(publishData, response);
667
672
  }
668
673
  }
@@ -6,9 +6,7 @@
6
6
  import { EventEmitter } from "events";
7
7
  import * as chalk from "chalk";
8
8
 
9
- import { AddressSpace, BaseNode, Duration, UAObjectType } from "node-opcua-address-space";
10
- import { checkSelectClauses } from "node-opcua-address-space";
11
- import { SessionContext } from "node-opcua-address-space";
9
+ import { SessionContext,AddressSpace, BaseNode, Duration, UAObjectType } from "node-opcua-address-space";
12
10
  import { assert } from "node-opcua-assert";
13
11
  import { Byte, UInt32 } from "node-opcua-basic-types";
14
12
  import { SubscriptionDiagnosticsDataType } from "node-opcua-common";
@@ -18,7 +16,7 @@ import { checkDebugFlag, make_debugLog, make_warningLog } from "node-opcua-debug
18
16
  import { NodeId } from "node-opcua-nodeid";
19
17
  import { ObjectRegistry } from "node-opcua-object-registry";
20
18
  import { SequenceNumberGenerator } from "node-opcua-secure-channel";
21
- import { EventFilter } from "node-opcua-service-filter";
19
+ import { EventFilter, checkSelectClauses } from "node-opcua-service-filter";
22
20
  import { AggregateFilter } from "node-opcua-service-subscription";
23
21
  import {
24
22
  DataChangeNotification,
@@ -629,7 +627,7 @@ export class Subscription extends EventEmitter {
629
627
  this.messageSent = false;
630
628
 
631
629
  this.timerId = null;
632
- this._start_timer();
630
+ this._start_timer({ firstTime: true });
633
631
 
634
632
  debugLog(chalk.green(`creating subscription ${this.id}`));
635
633
 
@@ -686,7 +684,7 @@ export class Subscription extends EventEmitter {
686
684
  // todo
687
685
  }
688
686
  this._stop_timer();
689
- this._start_timer();
687
+ this._start_timer({ firstTime: false });
690
688
  }
691
689
 
692
690
  /**
@@ -732,7 +730,7 @@ export class Subscription extends EventEmitter {
732
730
  public increaseLifeTimeCounter(): void {
733
731
  this._life_time_counter += 1;
734
732
  if (this._life_time_counter >= this.lifeTimeCount) {
735
- this.emit("lifeTimeExpired");
733
+ this.emit("lifeTimeExpired");
736
734
  }
737
735
  this.emit("lifeTimeCounterChanged", this._life_time_counter);
738
736
  }
@@ -1458,7 +1456,7 @@ export class Subscription extends EventEmitter {
1458
1456
  }
1459
1457
  }
1460
1458
 
1461
- private _start_timer() {
1459
+ private _start_timer({ firstTime }: { firstTime: boolean }) {
1462
1460
  debugLog(
1463
1461
  chalk.bgWhite.blue("Subscription#_start_timer subscriptionId="),
1464
1462
  this.id,
@@ -1478,8 +1476,11 @@ export class Subscription extends EventEmitter {
1478
1476
  // make sure that a keep-alive Message will be send at the end of the first publishing cycle
1479
1477
  // if there are no Notifications ready.
1480
1478
  this._keep_alive_counter = 0; // this.maxKeepAliveCount;
1481
- assert(this.messageSent === false);
1482
- assert(this.state === SubscriptionState.CREATING);
1479
+
1480
+ if (firstTime) {
1481
+ assert(this.messageSent === false);
1482
+ assert(this.state === SubscriptionState.CREATING);
1483
+ }
1483
1484
 
1484
1485
  assert(this.publishingInterval >= Subscription.minimumPublishingInterval);
1485
1486
  this.timerId = setInterval(this._tick.bind(this), this.publishingInterval);