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.
Files changed (75) hide show
  1. package/LICENSE +20 -20
  2. package/dist/base_server.js +12 -14
  3. package/dist/base_server.js.map +1 -1
  4. package/dist/factory.d.ts +4 -2
  5. package/dist/factory.js.map +1 -1
  6. package/dist/history_server_capabilities.js.map +1 -1
  7. package/dist/i_server_side_publish_engine.d.ts +1 -1
  8. package/dist/i_server_side_publish_engine.js +1 -1
  9. package/dist/i_server_side_publish_engine.js.map +1 -1
  10. package/dist/monitored_item.d.ts +3 -0
  11. package/dist/monitored_item.js +7 -14
  12. package/dist/monitored_item.js.map +1 -1
  13. package/dist/node_sampler.js +1 -1
  14. package/dist/node_sampler.js.map +1 -1
  15. package/dist/opcua_server.d.ts +29 -44
  16. package/dist/opcua_server.js +218 -262
  17. package/dist/opcua_server.js.map +1 -1
  18. package/dist/queue.js +1 -0
  19. package/dist/queue.js.map +1 -1
  20. package/dist/register_server_manager.d.ts +4 -1
  21. package/dist/register_server_manager.js +5 -5
  22. package/dist/register_server_manager.js.map +1 -1
  23. package/dist/register_server_manager_hidden.d.ts +1 -1
  24. package/dist/register_server_manager_hidden.js.map +1 -1
  25. package/dist/register_server_manager_mdns_only.d.ts +4 -1
  26. package/dist/register_server_manager_mdns_only.js +1 -1
  27. package/dist/register_server_manager_mdns_only.js.map +1 -1
  28. package/dist/server_capabilities.js.map +1 -1
  29. package/dist/server_end_point.d.ts +4 -1
  30. package/dist/server_end_point.js +10 -11
  31. package/dist/server_end_point.js.map +1 -1
  32. package/dist/server_engine.d.ts +11 -7
  33. package/dist/server_engine.js +72 -74
  34. package/dist/server_engine.js.map +1 -1
  35. package/dist/server_publish_engine.d.ts +4 -1
  36. package/dist/server_publish_engine.js +5 -5
  37. package/dist/server_publish_engine.js.map +1 -1
  38. package/dist/server_publish_engine_for_orphan_subscriptions.d.ts +2 -2
  39. package/dist/server_publish_engine_for_orphan_subscriptions.js.map +1 -1
  40. package/dist/server_session.d.ts +1 -1
  41. package/dist/server_session.js +24 -29
  42. package/dist/server_session.js.map +1 -1
  43. package/dist/server_subscription.d.ts +3 -1
  44. package/dist/server_subscription.js +6 -6
  45. package/dist/server_subscription.js.map +1 -1
  46. package/dist/sessions_compatible_for_transfer.js +2 -1
  47. package/dist/sessions_compatible_for_transfer.js.map +1 -1
  48. package/dist/validate_filter.js +4 -7
  49. package/dist/validate_filter.js.map +1 -1
  50. package/package.json +45 -44
  51. package/source/base_server.ts +19 -22
  52. package/source/factory.ts +5 -2
  53. package/source/history_server_capabilities.ts +3 -4
  54. package/source/i_channel_data.ts +4 -8
  55. package/source/i_register_server_manager.ts +0 -3
  56. package/source/i_server_side_publish_engine.ts +5 -6
  57. package/source/i_socket_data.ts +1 -1
  58. package/source/index.ts +14 -14
  59. package/source/monitored_item.ts +32 -44
  60. package/source/node_sampler.ts +82 -82
  61. package/source/opcua_server.ts +326 -357
  62. package/source/queue.ts +6 -7
  63. package/source/register_server_manager.ts +35 -23
  64. package/source/register_server_manager_hidden.ts +8 -10
  65. package/source/register_server_manager_mdns_only.ts +8 -13
  66. package/source/server_capabilities.ts +0 -5
  67. package/source/server_end_point.ts +28 -30
  68. package/source/server_engine.ts +122 -122
  69. package/source/server_publish_engine.ts +24 -21
  70. package/source/server_publish_engine_for_orphan_subscriptions.ts +26 -26
  71. package/source/server_session.ts +44 -49
  72. package/source/server_subscription.ts +23 -23
  73. package/source/sessions_compatible_for_transfer.ts +26 -25
  74. package/source/validate_filter.ts +8 -22
  75. package/test_helpers/create_certificates.js +1 -1
@@ -36,7 +36,9 @@ import {
36
36
  UAObject,
37
37
  UAVariable,
38
38
  ISessionContext,
39
- UAView
39
+ UAView,
40
+ EventTypeLike,
41
+ UAObjectType
40
42
  } from "node-opcua-address-space";
41
43
  import { getDefaultCertificateManager, OPCUACertificateManager } from "node-opcua-certificate-manager";
42
44
  import { ServerState } from "node-opcua-common";
@@ -112,7 +114,6 @@ import {
112
114
  SetMonitoringModeResponse,
113
115
  SetPublishingModeRequest,
114
116
  SetPublishingModeResponse,
115
- SetTriggeringRequestOptions,
116
117
  SetTriggeringRequest,
117
118
  SetTriggeringResponse,
118
119
  TransferSubscriptionsRequest,
@@ -135,15 +136,16 @@ import {
135
136
  MonitoringMode,
136
137
  UserIdentityToken,
137
138
  UserTokenPolicy,
138
- BrowseDescription,
139
139
  BuildInfoOptions,
140
140
  MonitoredItemCreateResult,
141
- IssuedIdentityToken
141
+ IssuedIdentityToken,
142
+ BrowseResultOptions
142
143
  } from "node-opcua-types";
143
144
  import { DataType } from "node-opcua-variant";
144
145
  import { VariantArrayType } from "node-opcua-variant";
145
146
  import { matchUri } from "node-opcua-utils";
146
147
 
148
+ import { UAString } from "node-opcua-basic-types";
147
149
  import { OPCUABaseServer, OPCUABaseServerOptions } from "./base_server";
148
150
  import { Factory } from "./factory";
149
151
  import { IRegisterServerManager } from "./i_register_server_manager";
@@ -153,7 +155,7 @@ import { RegisterServerManagerHidden } from "./register_server_manager_hidden";
153
155
  import { RegisterServerManagerMDNSONLY } from "./register_server_manager_mdns_only";
154
156
  import { ServerCapabilitiesOptions } from "./server_capabilities";
155
157
  import { OPCUAServerEndPoint } from "./server_end_point";
156
- import { ClosingReason, ServerEngine } from "./server_engine";
158
+ import { ClosingReason, CreateSessionOption, ServerEngine } from "./server_engine";
157
159
  import { ServerSession } from "./server_session";
158
160
  import { CreateMonitoredItemHook, DeleteMonitoredItemHook, Subscription } from "./server_subscription";
159
161
  import { ISocketData } from "./i_socket_data";
@@ -178,6 +180,8 @@ export interface UserManagerOptions extends IUserManager {
178
180
  isValidUserAsync?: ValidUserAsyncFunc;
179
181
  }
180
182
 
183
+ // tslint:disable-next-line:no-var-requires
184
+ const thenify = require("thenify");
181
185
  // tslint:disable-next-line:no-var-requires
182
186
  const package_info = require("../package.json");
183
187
  const debugLog = make_debugLog(__filename);
@@ -208,6 +212,26 @@ const minSessionTimeout = 100; // 100 milliseconds
208
212
  const defaultSessionTimeout = 1000 * 30; // 30 seconds
209
213
  const maxSessionTimeout = 1000 * 60 * 50; // 50 minutes
210
214
 
215
+ type ResponseClassType =
216
+ | typeof BrowseResponse
217
+ | typeof BrowseNextResponse
218
+ | typeof CallResponse
219
+ | typeof CreateMonitoredItemsResponse
220
+ | typeof CreateSubscriptionResponse
221
+ | typeof DeleteSubscriptionsResponse
222
+ | typeof HistoryReadResponse
223
+ | typeof ModifyMonitoredItemsResponse
224
+ | typeof ModifySubscriptionResponse
225
+ | typeof ReadResponse
226
+ | typeof RegisterNodesResponse
227
+ | typeof RepublishResponse
228
+ | typeof SetPublishingModeResponse
229
+ | typeof SetTriggeringResponse
230
+ | typeof TransferSubscriptionsResponse
231
+ | typeof TranslateBrowsePathsToNodeIdsResponse
232
+ | typeof UnregisterNodesResponse
233
+ | typeof WriteResponse;
234
+
211
235
  function _adjust_session_timeout(sessionTimeout: number) {
212
236
  let revisedSessionTimeout = sessionTimeout || defaultSessionTimeout;
213
237
  revisedSessionTimeout = Math.min(revisedSessionTimeout, maxSessionTimeout);
@@ -217,7 +241,7 @@ function _adjust_session_timeout(sessionTimeout: number) {
217
241
 
218
242
  function channel_has_session(channel: ServerSecureChannelLayer, session: ServerSession): boolean {
219
243
  if (session.channel === channel) {
220
- assert(channel.sessionTokens.hasOwnProperty(session.authenticationToken.toString()));
244
+ assert(Object.prototype.hasOwnProperty.call(channel.sessionTokens, session.authenticationToken.toString()));
221
245
  return true;
222
246
  }
223
247
  return false;
@@ -292,10 +316,7 @@ function _serverEndpointsForCreateSessionResponse(server: OPCUAServer, endpointU
292
316
  .map(getRequiredEndpointInfo);
293
317
  }
294
318
 
295
- function adjustSecurityPolicy(
296
- channel: ServerSecureChannelLayer,
297
- userTokenPolicy_securityPolicyUri: SecurityPolicy
298
- ): SecurityPolicy {
319
+ function adjustSecurityPolicy(channel: ServerSecureChannelLayer, userTokenPolicy_securityPolicyUri: UAString): SecurityPolicy {
299
320
  // check that userIdentityToken
300
321
  let securityPolicy = fromURI(userTokenPolicy_securityPolicyUri);
301
322
 
@@ -489,8 +510,7 @@ function build_scanning_node_function(
489
510
  oldDataValue: DataValue,
490
511
  callback: (err: Error | null, dataValue?: DataValue) => void
491
512
  ) {
492
- const self = this;
493
- assert(self instanceof MonitoredItem);
513
+ assert(this instanceof MonitoredItem);
494
514
  assert(oldDataValue instanceof DataValue);
495
515
  assert(typeof callback === "function");
496
516
  const newDataValue = node.readAttribute(null, itemToMonitor.attributeId);
@@ -580,6 +600,83 @@ function _installRegisterServerManager(self: OPCUAServer) {
580
600
  });
581
601
  }
582
602
 
603
+ function validate_applicationUri(channel: ServerSecureChannelLayer, request: CreateSessionRequest): boolean {
604
+ const applicationUri = request.clientDescription.applicationUri!;
605
+ const clientCertificate = request.clientCertificate;
606
+ // if session is insecure there is no need to check certificate information
607
+ if (channel.securityMode === MessageSecurityMode.None) {
608
+ return true; // assume correct
609
+ }
610
+ if (!clientCertificate || clientCertificate.length === 0) {
611
+ return true; // can't check
612
+ }
613
+ const e = exploreCertificate(clientCertificate);
614
+ const applicationUriFromCert = e.tbsCertificate.extensions!.subjectAltName.uniformResourceIdentifier[0];
615
+
616
+ /* istanbul ignore next */
617
+ if (applicationUriFromCert !== applicationUri) {
618
+ errorLog("BadCertificateUriInvalid!");
619
+ errorLog("applicationUri = ", applicationUri);
620
+ errorLog("applicationUriFromCert = ", applicationUriFromCert);
621
+ }
622
+
623
+ return applicationUriFromCert === applicationUri;
624
+ }
625
+
626
+ function validate_security_endpoint(
627
+ server: OPCUAServer,
628
+ request: CreateSessionRequest,
629
+ channel: ServerSecureChannelLayer
630
+ ): {
631
+ errCode: StatusCode;
632
+ endpoint?: EndpointDescription;
633
+ } {
634
+ debugLog("validate_security_endpoint = ", request.endpointUrl);
635
+ let endpoints = server._get_endpoints(request.endpointUrl);
636
+ // endpointUrl String The network address that the Client used to access the Session Endpoint.
637
+ // The HostName portion of the URL should be one of the HostNames for the application that are
638
+ // specified in the Server’s ApplicationInstanceCertificate (see 7.2). The Server shall raise an
639
+ // AuditUrlMismatchEventType event if the URL does not match the Server’s HostNames.
640
+ // AuditUrlMismatchEventType event type is defined in Part 5.
641
+ // The Server uses this information for diagnostics and to determine the set of
642
+ // EndpointDescriptions to return in the response.
643
+ // ToDo: check endpointUrl validity and emit an AuditUrlMismatchEventType event if not
644
+ if (endpoints.length === 0) {
645
+ // we have a UrlMismatch here
646
+ const ua_server = server.engine.addressSpace!.rootFolder.objects.server;
647
+ ua_server.raiseEvent("AuditUrlMismatchEventType", {
648
+ endpointUrl: { dataType: DataType.String, value: request.endpointUrl }
649
+ });
650
+ debugLog("Cannot find endpoint in available endpoints with endpointUri", request.endpointUrl);
651
+ if (OPCUAServer.requestExactEndpointUrl) {
652
+ return { errCode: StatusCodes.BadServiceUnsupported };
653
+ } else {
654
+ endpoints = server._get_endpoints(null);
655
+ }
656
+ }
657
+ // ignore restricted endpoints
658
+ endpoints = endpoints.filter((e: EndpointDescription) => !(e as any).restricted);
659
+
660
+ const endpoints_matching_security_mode = endpoints.filter((e: EndpointDescription) => {
661
+ return e.securityMode === channel.securityMode;
662
+ });
663
+
664
+ if (endpoints_matching_security_mode.length === 0) {
665
+ return { errCode: StatusCodes.BadSecurityModeRejected };
666
+ }
667
+ const endpoints_matching_security_policy = endpoints_matching_security_mode.filter((e: EndpointDescription) => {
668
+ return e.securityPolicyUri === channel.securityHeader!.securityPolicyUri;
669
+ });
670
+
671
+ if (endpoints_matching_security_policy.length === 0) {
672
+ return { errCode: StatusCodes.BadSecurityPolicyRejected };
673
+ }
674
+ if (endpoints_matching_security_policy.length !== 1) {
675
+ debugLog("endpoints_matching_security_policy= ", endpoints_matching_security_policy.length);
676
+ }
677
+ return { errCode: StatusCodes.Good, endpoint: endpoints_matching_security_policy[0] };
678
+ }
679
+
583
680
  export enum RegisterServerMethod {
584
681
  HIDDEN = 1, // the server doesn't expose itself to the external world
585
682
  MDNS = 2, // the server publish itself to the mDNS Multicast network directly
@@ -797,12 +894,12 @@ export interface OPCUAServer {
797
894
  userCertificateManager: OPCUACertificateManager;
798
895
  }
799
896
 
800
- const g_requestExactEndpointUrl: boolean = !!process.env.NODEOPCUA_SERVER_REQUEST_EXACT_ENDPOINT_URL;
897
+ const g_requestExactEndpointUrl = !!process.env.NODEOPCUA_SERVER_REQUEST_EXACT_ENDPOINT_URL;
801
898
  /**
802
899
  *
803
900
  */
804
901
  export class OPCUAServer extends OPCUABaseServer {
805
- static defaultShutdownTimeout: number = 100; // 250 ms
902
+ static defaultShutdownTimeout = 100; // 250 ms
806
903
  /**
807
904
  * if requestExactEndpointUrl is set to true the server will only accept createSession that have a endpointUrl that strictly matches
808
905
  * one of the provided endpoint.
@@ -851,8 +948,7 @@ export class OPCUAServer extends OPCUABaseServer {
851
948
  */
852
949
  public get currentChannelCount(): number {
853
950
  // TODO : move to base
854
- const self = this;
855
- return self.endpoints.reduce((currentValue: number, endPoint: OPCUAServerEndPoint) => {
951
+ return this.endpoints.reduce((currentValue: number, endPoint: OPCUAServerEndPoint) => {
856
952
  return currentValue + endPoint.currentChannelCount;
857
953
  }, 0);
858
954
  }
@@ -932,7 +1028,7 @@ export class OPCUAServer extends OPCUABaseServer {
932
1028
  /**
933
1029
  * false if anonymous connection are not allowed
934
1030
  */
935
- public allowAnonymous: boolean = false;
1031
+ public allowAnonymous = false;
936
1032
 
937
1033
  /**
938
1034
  * the user manager
@@ -947,6 +1043,7 @@ export class OPCUAServer extends OPCUABaseServer {
947
1043
  constructor(options?: OPCUAServerOptions) {
948
1044
  super(options);
949
1045
 
1046
+ this.allowAnonymous = false;
950
1047
  options = options || {};
951
1048
 
952
1049
  this.options = options;
@@ -1208,7 +1305,7 @@ export class OPCUAServer extends OPCUABaseServer {
1208
1305
  });
1209
1306
  }
1210
1307
 
1211
- public dispose() {
1308
+ public dispose(): void {
1212
1309
  for (const endpoint of this.endpoints) {
1213
1310
  endpoint.dispose();
1214
1311
  }
@@ -1228,7 +1325,7 @@ export class OPCUAServer extends OPCUABaseServer {
1228
1325
  }
1229
1326
  }
1230
1327
 
1231
- public raiseEvent(eventType: any, options: any): void {
1328
+ public raiseEvent(eventType: EventTypeLike | UAObjectType, options: RaiseEventData): void {
1232
1329
  /* istanbul ignore next */
1233
1330
  if (!this.engine.addressSpace) {
1234
1331
  errorLog("addressSpace missing");
@@ -1243,16 +1340,16 @@ export class OPCUAServer extends OPCUABaseServer {
1243
1340
  return;
1244
1341
  }
1245
1342
 
1246
- let eventTypeNode = eventType;
1343
+ let eventTypeNode: EventTypeLike | UAObjectType | null = eventType;
1247
1344
  if (typeof eventType === "string") {
1248
1345
  eventTypeNode = this.engine.addressSpace.findEventType(eventType);
1249
- }
1250
-
1251
- /* istanbul ignore else */
1252
- if (eventTypeNode) {
1253
- return server.raiseEvent(eventTypeNode, options);
1346
+ if (eventTypeNode) {
1347
+ return server.raiseEvent(eventTypeNode, options);
1348
+ } else {
1349
+ console.warn(" cannot find event type ", eventType);
1350
+ }
1254
1351
  } else {
1255
- console.warn(" cannot find event type ", eventType);
1352
+ return server.raiseEvent(eventTypeNode, options);
1256
1353
  }
1257
1354
  }
1258
1355
 
@@ -1260,7 +1357,7 @@ export class OPCUAServer extends OPCUABaseServer {
1260
1357
  * create and register a new session
1261
1358
  * @internal
1262
1359
  */
1263
- protected createSession(options: any): ServerSession {
1360
+ protected createSession(options: CreateSessionOption): ServerSession {
1264
1361
  /* istanbul ignore next */
1265
1362
  if (!this.engine) {
1266
1363
  throw new Error("Internal Error");
@@ -1315,11 +1412,11 @@ export class OPCUAServer extends OPCUABaseServer {
1315
1412
  protected isValidUserNameIdentityToken(
1316
1413
  channel: ServerSecureChannelLayer,
1317
1414
  session: ServerSession,
1318
- userTokenPolicy: any,
1415
+ userTokenPolicy: UserTokenPolicy,
1319
1416
  userIdentityToken: UserNameIdentityToken,
1320
- userTokenSignature: any,
1417
+ userTokenSignature: SignatureData,
1321
1418
  callback: (err: Error | null, statusCode?: StatusCode) => void
1322
- ) {
1419
+ ): void {
1323
1420
  assert(userIdentityToken instanceof UserNameIdentityToken);
1324
1421
 
1325
1422
  const securityPolicy = adjustSecurityPolicy(channel, userTokenPolicy.securityPolicyUri);
@@ -1351,11 +1448,11 @@ export class OPCUAServer extends OPCUABaseServer {
1351
1448
  protected isValidX509IdentityToken(
1352
1449
  channel: ServerSecureChannelLayer,
1353
1450
  session: ServerSession,
1354
- userTokenPolicy: any,
1451
+ userTokenPolicy: UserTokenPolicy,
1355
1452
  userIdentityToken: X509IdentityToken,
1356
- userTokenSignature: any,
1453
+ userTokenSignature: SignatureData,
1357
1454
  callback: (err: Error | null, statusCode?: StatusCode) => void
1358
- ) {
1455
+ ): void {
1359
1456
  assert(userIdentityToken instanceof X509IdentityToken);
1360
1457
  assert(callback instanceof Function);
1361
1458
 
@@ -1433,7 +1530,7 @@ export class OPCUAServer extends OPCUABaseServer {
1433
1530
  protected userNameIdentityTokenAuthenticateUser(
1434
1531
  channel: ServerSecureChannelLayer,
1435
1532
  session: ServerSession,
1436
- userTokenPolicy: any,
1533
+ userTokenPolicy: UserTokenPolicy,
1437
1534
  userIdentityToken: UserNameIdentityToken,
1438
1535
  callback: (err: Error | null, isAuthorized?: boolean) => void
1439
1536
  ): void {
@@ -1488,7 +1585,7 @@ export class OPCUAServer extends OPCUABaseServer {
1488
1585
  channel: ServerSecureChannelLayer,
1489
1586
  session: ServerSession,
1490
1587
  userIdentityToken: UserIdentityToken,
1491
- userTokenSignature: any,
1588
+ userTokenSignature: SignatureData,
1492
1589
  endpointDescription: EndpointDescription,
1493
1590
  callback: (err: Error | null, statusCode?: StatusCode) => void
1494
1591
  ): void {
@@ -1544,13 +1641,16 @@ export class OPCUAServer extends OPCUABaseServer {
1544
1641
  session: ServerSession,
1545
1642
  userIdentityToken: UserIdentityToken,
1546
1643
  callback: (err: Error | null, isAuthorized?: boolean) => void
1547
- ) {
1644
+ ): void {
1548
1645
  assert(userIdentityToken);
1549
1646
  assert(typeof callback === "function");
1550
1647
 
1551
1648
  const userTokenType = getTokenType(userIdentityToken);
1552
1649
  const userTokenPolicy = findUserTokenByPolicy(session.getEndpointDescription(), userTokenType, userIdentityToken.policyId!);
1553
- assert(userTokenPolicy);
1650
+ /** istanbul ignore next */
1651
+ if (!userTokenPolicy) {
1652
+ return callback(null, false);
1653
+ }
1554
1654
  // find if a userToken exists
1555
1655
  if (userIdentityToken instanceof UserNameIdentityToken) {
1556
1656
  return this.userNameIdentityTokenAuthenticateUser(channel, session, userTokenPolicy, userIdentityToken, callback);
@@ -1563,12 +1663,12 @@ export class OPCUAServer extends OPCUABaseServer {
1563
1663
  }
1564
1664
 
1565
1665
  // session services
1566
- protected async _on_CreateSessionRequest(message: Message, channel: ServerSecureChannelLayer) {
1567
- const server = this;
1666
+ // eslint-disable-next-line max-statements
1667
+ protected async _on_CreateSessionRequest(message: Message, channel: ServerSecureChannelLayer): Promise<void> {
1568
1668
  const request = message.request as CreateSessionRequest;
1569
1669
  assert(request instanceof CreateSessionRequest);
1570
1670
 
1571
- function rejectConnection(statusCode: StatusCode): void {
1671
+ function rejectConnection(server: OPCUAServer, statusCode: StatusCode): void {
1572
1672
  server.engine.incrementSecurityRejectedSessionCount();
1573
1673
 
1574
1674
  const response1 = new CreateSessionResponse({
@@ -1582,13 +1682,13 @@ export class OPCUAServer extends OPCUABaseServer {
1582
1682
  // A Server application should limit the number of Sessions. To protect against misbehaving Clients and denial
1583
1683
  // of service attacks, the Server shall close the oldest Session that is not activated before reaching the
1584
1684
  // maximum number of supported Sessions
1585
- if (server.currentSessionCount >= server.maxAllowedSessionNumber) {
1586
- await _attempt_to_close_some_old_unactivated_session(server);
1685
+ if (this.currentSessionCount >= this.maxAllowedSessionNumber) {
1686
+ await _attempt_to_close_some_old_unactivated_session(this);
1587
1687
  }
1588
1688
 
1589
1689
  // check if session count hasn't reach the maximum allowed sessions
1590
- if (server.currentSessionCount >= server.maxAllowedSessionNumber) {
1591
- return rejectConnection(StatusCodes.BadTooManySessions);
1690
+ if (this.currentSessionCount >= this.maxAllowedSessionNumber) {
1691
+ return rejectConnection(this, StatusCodes.BadTooManySessions);
1592
1692
  }
1593
1693
 
1594
1694
  // Release 1.03 OPC Unified Architecture, Part 4 page 24 - CreateSession Parameters
@@ -1626,7 +1726,7 @@ export class OPCUAServer extends OPCUABaseServer {
1626
1726
  request.clientNonce && request.clientNonce.toString("hex")
1627
1727
  );
1628
1728
 
1629
- return rejectConnection(StatusCodes.BadNonceInvalid);
1729
+ return rejectConnection(this, StatusCodes.BadNonceInvalid);
1630
1730
  }
1631
1731
  }
1632
1732
  if (nonceAlreadyBeenUsed(request.clientNonce)) {
@@ -1635,93 +1735,21 @@ export class OPCUAServer extends OPCUABaseServer {
1635
1735
  request.clientNonce && request.clientNonce.toString("hex")
1636
1736
  );
1637
1737
 
1638
- return rejectConnection(StatusCodes.BadNonceInvalid);
1738
+ return rejectConnection(this, StatusCodes.BadNonceInvalid);
1639
1739
  }
1640
-
1641
- function validate_applicationUri(applicationUri: string, clientCertificate: Certificate): boolean {
1642
- // if session is insecure there is no need to check certificate information
1643
- if (channel.securityMode === MessageSecurityMode.None) {
1644
- return true; // assume correct
1645
- }
1646
- if (!clientCertificate || clientCertificate.length === 0) {
1647
- return true; // can't check
1648
- }
1649
- const e = exploreCertificate(clientCertificate);
1650
- const applicationUriFromCert = e.tbsCertificate.extensions!.subjectAltName.uniformResourceIdentifier[0];
1651
-
1652
- /* istanbul ignore next */
1653
- if (applicationUriFromCert !== applicationUri) {
1654
- errorLog("BadCertificateUriInvalid!");
1655
- errorLog("applicationUri = ", applicationUri);
1656
- errorLog("applicationUriFromCert = ", applicationUriFromCert);
1657
- }
1658
-
1659
- return applicationUriFromCert === applicationUri;
1660
- }
1661
-
1662
1740
  // check application spoofing
1663
1741
  // check if applicationUri in createSessionRequest matches applicationUri in client Certificate
1664
- if (!validate_applicationUri(request.clientDescription.applicationUri!, request.clientCertificate)) {
1665
- return rejectConnection(StatusCodes.BadCertificateUriInvalid);
1666
- }
1667
-
1668
- function validate_security_endpoint(channel1: ServerSecureChannelLayer): {
1669
- errCode: StatusCode;
1670
- endpoint?: EndpointDescription;
1671
- } {
1672
- debugLog("validate_security_endpoint = ", request.endpointUrl);
1673
- let endpoints = server._get_endpoints(request.endpointUrl);
1674
- // endpointUrl String The network address that the Client used to access the Session Endpoint.
1675
- // The HostName portion of the URL should be one of the HostNames for the application that are
1676
- // specified in the Server’s ApplicationInstanceCertificate (see 7.2). The Server shall raise an
1677
- // AuditUrlMismatchEventType event if the URL does not match the Server’s HostNames.
1678
- // AuditUrlMismatchEventType event type is defined in Part 5.
1679
- // The Server uses this information for diagnostics and to determine the set of
1680
- // EndpointDescriptions to return in the response.
1681
- // ToDo: check endpointUrl validity and emit an AuditUrlMismatchEventType event if not
1682
- if (endpoints.length === 0) {
1683
- // we have a UrlMismatch here
1684
- const ua_server = server.engine.addressSpace!.rootFolder.objects.server;
1685
- ua_server.raiseEvent("AuditUrlMismatchEventType", {
1686
- endpointUrl: { dataType: DataType.String, value: request.endpointUrl }
1687
- });
1688
- debugLog("Cannot find endpoint in available endpoints with endpointUri", request.endpointUrl);
1689
- if (OPCUAServer.requestExactEndpointUrl) {
1690
- return { errCode: StatusCodes.BadServiceUnsupported };
1691
- } else {
1692
- endpoints = server._get_endpoints(null);
1693
- }
1694
- }
1695
- // ignore restricted endpoints
1696
- endpoints = endpoints.filter((e: EndpointDescription) => !(e as any).restricted);
1697
-
1698
- const endpoints_matching_security_mode = endpoints.filter((e: EndpointDescription) => {
1699
- return e.securityMode === channel1.securityMode;
1700
- });
1701
-
1702
- if (endpoints_matching_security_mode.length === 0) {
1703
- return { errCode: StatusCodes.BadSecurityModeRejected };
1704
- }
1705
- const endpoints_matching_security_policy = endpoints_matching_security_mode.filter((e: EndpointDescription) => {
1706
- return e.securityPolicyUri === channel1.securityHeader!.securityPolicyUri;
1707
- });
1708
-
1709
- if (endpoints_matching_security_policy.length === 0) {
1710
- return { errCode: StatusCodes.BadSecurityPolicyRejected };
1711
- }
1712
- if (endpoints_matching_security_policy.length !== 1) {
1713
- debugLog("endpoints_matching_security_policy= ", endpoints_matching_security_policy.length);
1714
- }
1715
- return { errCode: StatusCodes.Good, endpoint: endpoints_matching_security_policy[0] };
1742
+ if (!validate_applicationUri(channel, request)) {
1743
+ return rejectConnection(this, StatusCodes.BadCertificateUriInvalid);
1716
1744
  }
1717
1745
 
1718
- const { errCode, endpoint } = validate_security_endpoint(channel);
1746
+ const { errCode, endpoint } = validate_security_endpoint(this, request, channel);
1719
1747
  if (errCode !== StatusCodes.Good) {
1720
- return rejectConnection(errCode);
1748
+ return rejectConnection(this, errCode);
1721
1749
  }
1722
1750
 
1723
1751
  // see Release 1.02 27 OPC Unified Architecture, Part 4
1724
- const session = server.createSession({
1752
+ const session = this.createSession({
1725
1753
  clientDescription: request.clientDescription,
1726
1754
  sessionTimeout: revisedSessionTimeout
1727
1755
  });
@@ -1747,12 +1775,12 @@ export class OPCUAServer extends OPCUABaseServer {
1747
1775
  //
1748
1776
  // ( this serverNonce will only be used up to the _on_ActivateSessionRequest
1749
1777
  // where a new nonce will be created)
1750
- session.nonce = server.makeServerNonce();
1778
+ session.nonce = this.makeServerNonce();
1751
1779
  session.channelId = channel.channelId;
1752
1780
 
1753
1781
  session._attach_channel(channel);
1754
1782
 
1755
- const serverCertificateChain = server.getCertificateChain();
1783
+ const serverCertificateChain = this.getCertificateChain();
1756
1784
 
1757
1785
  const hasEncryption = true;
1758
1786
  // If the securityPolicyUri is None and none of the UserTokenPolicies requires encryption
@@ -1793,7 +1821,7 @@ export class OPCUAServer extends OPCUABaseServer {
1793
1821
  // securityPolicyUri, userIdentityTokens, transportProfileUri and securityLevel with all
1794
1822
  // other parameters set to null. Only the recommended parameters shall be verified by
1795
1823
  // the client.
1796
- serverEndpoints: _serverEndpointsForCreateSessionResponse(server, session.endpoint!.endpointUrl, request.serverUri),
1824
+ serverEndpoints: _serverEndpointsForCreateSessionResponse(this, session.endpoint!.endpointUrl, request.serverUri),
1797
1825
 
1798
1826
  // This parameter is deprecated and the array shall be empty.
1799
1827
  serverSoftwareCertificates: null,
@@ -1804,7 +1832,7 @@ export class OPCUAServer extends OPCUABaseServer {
1804
1832
  // The SignatureAlgorithm shall be the AsymmetricSignatureAlgorithm specified in the
1805
1833
  // SecurityPolicy for the Endpoint.
1806
1834
  // The SignatureData type is defined in 7.30.
1807
- serverSignature: server.computeServerSignature(channel, request.clientCertificate, request.clientNonce),
1835
+ serverSignature: this.computeServerSignature(channel, request.clientCertificate, request.clientNonce),
1808
1836
 
1809
1837
  // The maximum message size accepted by the server
1810
1838
  // The Client Communication Stack should return a Bad_RequestTooLarge error to the
@@ -1813,15 +1841,15 @@ export class OPCUAServer extends OPCUABaseServer {
1813
1841
  maxRequestMessageSize: 0x4000000
1814
1842
  });
1815
1843
 
1816
- server.emit("create_session", session);
1844
+ this.emit("create_session", session);
1817
1845
 
1818
1846
  session.on("session_closed", (session1: ServerSession, deleteSubscriptions: boolean, reason: string) => {
1819
1847
  assert(typeof reason === "string");
1820
- if (server.isAuditing) {
1848
+ if (this.isAuditing) {
1821
1849
  assert(reason === "Timeout" || reason === "Terminated" || reason === "CloseSession" || reason === "Forcing");
1822
1850
  const sourceName = "Session/" + reason;
1823
1851
 
1824
- server.raiseEvent("AuditSessionEventType", {
1852
+ this.raiseEvent("AuditSessionEventType", {
1825
1853
  /* part 5 - 6.4.3 AuditEventType */
1826
1854
  actionTimeStamp: { dataType: "DateTime", value: new Date() },
1827
1855
  status: { dataType: "Boolean", value: true },
@@ -1842,12 +1870,12 @@ export class OPCUAServer extends OPCUABaseServer {
1842
1870
  });
1843
1871
  }
1844
1872
 
1845
- server.emit("session_closed", session1, deleteSubscriptions);
1873
+ this.emit("session_closed", session1, deleteSubscriptions);
1846
1874
  });
1847
1875
 
1848
- if (server.isAuditing) {
1876
+ if (this.isAuditing) {
1849
1877
  // ------------------------------------------------------------------------------------------------------
1850
- server.raiseEvent("AuditCreateSessionEventType", {
1878
+ this.raiseEvent("AuditCreateSessionEventType", {
1851
1879
  /* part 5 - 6.4.3 AuditEventType */
1852
1880
  actionTimeStamp: { dataType: "DateTime", value: new Date() },
1853
1881
  status: { dataType: "Boolean", value: true },
@@ -1881,7 +1909,7 @@ export class OPCUAServer extends OPCUABaseServer {
1881
1909
 
1882
1910
  // clientCertificateThumbprint
1883
1911
  clientCertificateThumbprint: {
1884
- dataType: "ByteString",
1912
+ dataType: "String",
1885
1913
  value: thumbprint(session.channel!.clientCertificate!)
1886
1914
  }
1887
1915
  });
@@ -1909,17 +1937,16 @@ export class OPCUAServer extends OPCUABaseServer {
1909
1937
  *
1910
1938
  *
1911
1939
  */
1912
- protected _on_ActivateSessionRequest(message: Message, channel: ServerSecureChannelLayer) {
1913
- const server = this;
1940
+ protected _on_ActivateSessionRequest(message: Message, channel: ServerSecureChannelLayer): void {
1914
1941
  const request = message.request as ActivateSessionRequest;
1915
1942
  assert(request instanceof ActivateSessionRequest);
1916
1943
 
1917
1944
  // get session from authenticationToken
1918
1945
  const authenticationToken = request.requestHeader.authenticationToken;
1919
1946
 
1920
- const session = server.getSession(authenticationToken);
1947
+ const session = this.getSession(authenticationToken);
1921
1948
 
1922
- function rejectConnection(statusCode: StatusCode): void {
1949
+ function rejectConnection(server: OPCUAServer, statusCode: StatusCode): void {
1923
1950
  if (statusCode === StatusCodes.BadSessionIdInvalid) {
1924
1951
  server.engine.incrementRejectedSessionCount();
1925
1952
  } else {
@@ -1941,7 +1968,7 @@ export class OPCUAServer extends OPCUABaseServer {
1941
1968
  // that the previous session may still be active
1942
1969
  debugLog(chalk.yellow.bold(" Bad Session in _on_ActivateSessionRequest"), authenticationToken.toString());
1943
1970
 
1944
- return rejectConnection(StatusCodes.BadSessionIdInvalid);
1971
+ return rejectConnection(this, StatusCodes.BadSessionIdInvalid);
1945
1972
  }
1946
1973
 
1947
1974
  // tslint:disable-next-line: no-unused-expression
@@ -1956,7 +1983,7 @@ export class OPCUAServer extends OPCUABaseServer {
1956
1983
  // it looks like session activation is being using a channel that is not the
1957
1984
  // one that have been used to create the session
1958
1985
  errorLog(" channel.sessionTokens === " + Object.keys(channel.sessionTokens).join(" "));
1959
- return rejectConnection(StatusCodes.BadSessionNotActivated);
1986
+ return rejectConnection(this, StatusCodes.BadSessionNotActivated);
1960
1987
  }
1961
1988
  }
1962
1989
 
@@ -1983,35 +2010,35 @@ export class OPCUAServer extends OPCUABaseServer {
1983
2010
  const new_channel_cert_thumbprint = thumbprint(channel.clientCertificate!);
1984
2011
 
1985
2012
  if (old_channel_cert_thumbprint !== new_channel_cert_thumbprint) {
1986
- return rejectConnection(StatusCodes.BadNoValidCertificates); // not sure about this code !
2013
+ return rejectConnection(this, StatusCodes.BadNoValidCertificates); // not sure about this code !
1987
2014
  }
1988
2015
 
1989
2016
  // ... In addition the Server shall verify that the Client supplied a UserIdentityToken that is
1990
2017
  // identical to the token currently associated with the Session reassign session to new channel.
1991
2018
  if (!sameIdentityToken(session.userIdentityToken!, request.userIdentityToken as UserIdentityToken)) {
1992
- return rejectConnection(StatusCodes.BadIdentityChangeNotSupported); // not sure about this code !
2019
+ return rejectConnection(this, StatusCodes.BadIdentityChangeNotSupported); // not sure about this code !
1993
2020
  }
1994
2021
  }
1995
2022
 
1996
2023
  moveSessionToChannel(session, channel);
1997
2024
  } else if (session.status === "screwed") {
1998
2025
  // session has been used before being activated => this should be detected and session should be dismissed.
1999
- return rejectConnection(StatusCodes.BadSessionClosed);
2026
+ return rejectConnection(this, StatusCodes.BadSessionClosed);
2000
2027
  } else if (session.status === "closed") {
2001
2028
  warningLog(chalk.yellow.bold(" Bad Session Closed in _on_ActivateSessionRequest"), authenticationToken.toString());
2002
- return rejectConnection(StatusCodes.BadSessionClosed);
2029
+ return rejectConnection(this, StatusCodes.BadSessionClosed);
2003
2030
  }
2004
2031
 
2005
2032
  // verify clientSignature provided by the client
2006
- if (!server.verifyClientSignature(session, channel, request.clientSignature)) {
2007
- return rejectConnection(StatusCodes.BadApplicationSignatureInvalid);
2033
+ if (!this.verifyClientSignature(session, channel, request.clientSignature)) {
2034
+ return rejectConnection(this, StatusCodes.BadApplicationSignatureInvalid);
2008
2035
  }
2009
2036
 
2010
2037
  // userIdentityToken may be missing , assume anonymous access then
2011
2038
  request.userIdentityToken = request.userIdentityToken || createAnonymousIdentityToken(session.endpoint!);
2012
2039
 
2013
2040
  // check request.userIdentityToken is correct ( expected type and correctly formed)
2014
- server.isValidUserIdentityToken(
2041
+ this.isValidUserIdentityToken(
2015
2042
  channel,
2016
2043
  session,
2017
2044
  request.userIdentityToken as UserIdentityToken,
@@ -2024,28 +2051,28 @@ export class OPCUAServer extends OPCUABaseServer {
2024
2051
  const a = 23;
2025
2052
  }
2026
2053
  assert(statusCode && statusCode instanceof StatusCode, "expecting statusCode");
2027
- return rejectConnection(statusCode!);
2054
+ return rejectConnection(this, statusCode!);
2028
2055
  }
2029
2056
  session.userIdentityToken = request.userIdentityToken as UserIdentityToken;
2030
2057
 
2031
2058
  // check if user access is granted
2032
- server.isUserAuthorized(
2059
+ this.isUserAuthorized(
2033
2060
  channel,
2034
2061
  session,
2035
2062
  request.userIdentityToken as UserIdentityToken,
2036
2063
  (err1: Error | null, authorized?: boolean) => {
2037
2064
  /* istanbul ignore next */
2038
2065
  if (err1) {
2039
- return rejectConnection(StatusCodes.BadInternalError);
2066
+ return rejectConnection(this, StatusCodes.BadInternalError);
2040
2067
  }
2041
2068
 
2042
2069
  if (!authorized) {
2043
- return rejectConnection(StatusCodes.BadUserAccessDenied);
2070
+ return rejectConnection(this, StatusCodes.BadUserAccessDenied);
2044
2071
  } else {
2045
2072
  // extract : OPC UA part 4 - 5.6.3
2046
2073
  // Once used, a serverNonce cannot be used again. For that reason, the Server returns a new
2047
2074
  // serverNonce each time the ActivateSession Service is called.
2048
- session.nonce = server.makeServerNonce();
2075
+ session.nonce = this.makeServerNonce();
2049
2076
 
2050
2077
  session.status = "active";
2051
2078
 
@@ -2067,8 +2094,8 @@ export class OPCUAServer extends OPCUABaseServer {
2067
2094
  // xx assert(session.channel.clientCertificate instanceof Buffer);
2068
2095
  assert(session.sessionTimeout > 0);
2069
2096
 
2070
- if (server.isAuditing) {
2071
- server.raiseEvent("AuditActivateSessionEventType", {
2097
+ if (this.isAuditing) {
2098
+ this.raiseEvent("AuditActivateSessionEventType", {
2072
2099
  /* part 5 - 6.4.3 AuditEventType */
2073
2100
  actionTimeStamp: { dataType: "DateTime", value: new Date() },
2074
2101
  status: { dataType: "Boolean", value: true },
@@ -2109,7 +2136,7 @@ export class OPCUAServer extends OPCUABaseServer {
2109
2136
  secureChannelId: { dataType: "String", value: session.channel!.channelId!.toString() }
2110
2137
  });
2111
2138
  }
2112
- server.emit("session_activated", session, userIdentityTokenPasswordRemoved);
2139
+ this.emit("session_activated", session, userIdentityTokenPasswordRemoved);
2113
2140
  }
2114
2141
  }
2115
2142
  );
@@ -2117,13 +2144,12 @@ export class OPCUAServer extends OPCUABaseServer {
2117
2144
  );
2118
2145
  }
2119
2146
 
2120
- protected prepare(message: Message, channel: ServerSecureChannelLayer) {
2121
- const server = this;
2147
+ protected prepare(message: Message, channel: ServerSecureChannelLayer): void {
2122
2148
  const request = message.request;
2123
2149
 
2124
2150
  // --- check that session is correct
2125
2151
  const authenticationToken = request.requestHeader.authenticationToken;
2126
- const session = server.getSession(authenticationToken, /*activeOnly*/ true);
2152
+ const session = this.getSession(authenticationToken, /*activeOnly*/ true);
2127
2153
  if (!session) {
2128
2154
  message.session_statusCode = StatusCodes.BadSessionIdInvalid;
2129
2155
  return;
@@ -2150,27 +2176,27 @@ export class OPCUAServer extends OPCUABaseServer {
2150
2176
  * @param ResponseClass the constructor of the response Class
2151
2177
  * @param message
2152
2178
  * @param channel
2153
- * @param action_to_perform
2154
- * @param action_to_perform.session {ServerSession}
2155
- * @param action_to_perform.sendResponse
2156
- * @param action_to_perform.sendResponse.response
2157
- * @param action_to_perform.sendError
2158
- * @param action_to_perform.sendError.statusCode
2159
- * @param action_to_perform.sendError.diagnostics
2179
+ * @param actionToPerform
2180
+ * @param actionToPerform.session {ServerSession}
2181
+ * @param actionToPerform.sendResponse
2182
+ * @param actionToPerform.sendResponse.response
2183
+ * @param actionToPerform.sendError
2184
+ * @param actionToPerform.sendError.statusCode
2185
+ * @param actionToPerform.sendError.diagnostics
2160
2186
  *
2161
2187
  * @private
2162
2188
  */
2163
2189
  protected async _apply_on_SessionObject(
2164
- ResponseClass: any,
2190
+ ResponseClass: ResponseClassType,
2165
2191
  message: Message,
2166
2192
  channel: ServerSecureChannelLayer,
2167
- action_to_perform: (
2193
+ actionToPerform: (
2168
2194
  session: ServerSession,
2169
2195
  sendResponse: (response: Response) => void,
2170
2196
  sendError: (statusCode: StatusCode) => void
2171
2197
  ) => void | Promise<void>
2172
- ) {
2173
- assert(typeof action_to_perform === "function");
2198
+ ): Promise<void> {
2199
+ assert(typeof actionToPerform === "function");
2174
2200
 
2175
2201
  function sendResponse(response1: Response) {
2176
2202
  try {
@@ -2247,31 +2273,23 @@ export class OPCUAServer extends OPCUABaseServer {
2247
2273
  message.session.keepAlive();
2248
2274
  }
2249
2275
  message.session.incrementTotalRequestCount();
2250
- await action_to_perform(message.session as ServerSession, sendResponse, sendError);
2276
+ await actionToPerform(message.session as ServerSession, sendResponse, sendError);
2251
2277
  }
2252
2278
 
2253
- /**
2254
- * @method _apply_on_Subscription
2255
- * @param ResponseClass
2256
- * @param message
2257
- * @param channel
2258
- * @param action_to_perform
2259
- * @private
2260
- */
2261
2279
  protected async _apply_on_Subscription(
2262
- ResponseClass: any,
2280
+ ResponseClass: ResponseClassType,
2263
2281
  message: Message,
2264
2282
  channel: ServerSecureChannelLayer,
2265
- action_to_perform: (
2283
+ actionToPerform: (
2266
2284
  session: ServerSession,
2267
2285
  subscription: Subscription,
2268
2286
  sendResponse: (response: Response) => void,
2269
2287
  sendError: (statusCode: StatusCode) => void
2270
2288
  ) => Promise<void>
2271
- ) {
2272
- assert(typeof action_to_perform === "function");
2289
+ ): Promise<void> {
2290
+ assert(typeof actionToPerform === "function");
2273
2291
  const request = message.request as unknown as { subscriptionId: number };
2274
- assert(request.hasOwnProperty("subscriptionId"));
2292
+ assert(Object.prototype.hasOwnProperty.call(request, "subscriptionId"));
2275
2293
 
2276
2294
  this._apply_on_SessionObject(
2277
2295
  ResponseClass,
@@ -2287,28 +2305,20 @@ export class OPCUAServer extends OPCUABaseServer {
2287
2305
  return sendError(StatusCodes.BadSubscriptionIdInvalid);
2288
2306
  }
2289
2307
  subscription.resetLifeTimeAndKeepAliveCounters();
2290
- await action_to_perform(session, subscription, sendResponse, sendError);
2308
+ await actionToPerform(session, subscription, sendResponse, sendError);
2291
2309
  }
2292
2310
  );
2293
2311
  }
2294
2312
 
2295
- /**
2296
- * @method _apply_on_SubscriptionIds
2297
- * @param ResponseClass
2298
- * @param message
2299
- * @param channel
2300
- * @param action_to_perform
2301
- * @private
2302
- */
2303
2313
  protected _apply_on_SubscriptionIds<T>(
2304
2314
  ResponseClass: typeof SetPublishingModeResponse | typeof TransferSubscriptionsResponse | typeof DeleteSubscriptionsResponse,
2305
2315
  message: Message,
2306
2316
  channel: ServerSecureChannelLayer,
2307
- action_to_perform: (session: ServerSession, subscriptionId: number) => Promise<T>
2308
- ) {
2309
- assert(typeof action_to_perform === "function");
2317
+ actionToPerform: (session: ServerSession, subscriptionId: number) => Promise<T>
2318
+ ): void {
2319
+ assert(typeof actionToPerform === "function");
2310
2320
  const request = message.request as unknown as { subscriptionIds: number[] };
2311
- assert(request.hasOwnProperty("subscriptionIds"));
2321
+ assert(Object.prototype.hasOwnProperty.call(request, "subscriptionIds"));
2312
2322
 
2313
2323
  this._apply_on_SessionObject(
2314
2324
  ResponseClass,
@@ -2329,7 +2339,7 @@ export class OPCUAServer extends OPCUABaseServer {
2329
2339
  // return sendError(StatusCodes.BadTooManyOperations);
2330
2340
  // }
2331
2341
 
2332
- const results: any[] = subscriptionIds.map((subscriptionId: number) => action_to_perform(session, subscriptionId));
2342
+ const results: any[] = subscriptionIds.map((subscriptionId: number) => actionToPerform(session, subscriptionId));
2333
2343
 
2334
2344
  // resolve potential pending promises ....
2335
2345
  for (let i = 0; i < results.length; i++) {
@@ -2352,20 +2362,12 @@ export class OPCUAServer extends OPCUABaseServer {
2352
2362
  );
2353
2363
  }
2354
2364
 
2355
- /**
2356
- * @method _apply_on_Subscriptions
2357
- * @param ResponseClass
2358
- * @param message
2359
- * @param channel
2360
- * @param action_to_perform
2361
- * @private
2362
- */
2363
2365
  protected _apply_on_Subscriptions(
2364
- ResponseClass: typeof SetPublishingModeResponse,
2366
+ ResponseClass: typeof SetPublishingModeResponse | typeof TransferSubscriptionsResponse | typeof DeleteSubscriptionsResponse,
2365
2367
  message: Message,
2366
2368
  channel: ServerSecureChannelLayer,
2367
- action_to_perform: (session: ServerSession, subscription: Subscription) => Promise<StatusCode>
2368
- ) {
2369
+ actionToPerform: (session: ServerSession, subscription: Subscription) => Promise<StatusCode>
2370
+ ): void {
2369
2371
  this._apply_on_SubscriptionIds<StatusCode>(
2370
2372
  ResponseClass,
2371
2373
  message,
@@ -2379,15 +2381,12 @@ export class OPCUAServer extends OPCUABaseServer {
2379
2381
  if (!subscription) {
2380
2382
  return StatusCodes.BadSubscriptionIdInvalid;
2381
2383
  }
2382
- return action_to_perform(session, subscription);
2384
+ return actionToPerform(session, subscription);
2383
2385
  }
2384
2386
  );
2385
2387
  }
2386
2388
 
2387
- private async _closeSession(authenticationToken: NodeId, deleteSubscriptions: boolean, reason: ClosingReason) {
2388
- const server = this;
2389
-
2390
- //
2389
+ private async _closeSession(authenticationToken: NodeId, deleteSubscriptions: boolean, reason: ClosingReason): Promise<void> {
2391
2390
  if (deleteSubscriptions && this.options.onDeleteMonitoredItem) {
2392
2391
  const session = this.getSession(authenticationToken);
2393
2392
  if (session) {
@@ -2397,7 +2396,7 @@ export class OPCUAServer extends OPCUABaseServer {
2397
2396
  }
2398
2397
  }
2399
2398
  }
2400
- await server.engine.closeSession(authenticationToken, deleteSubscriptions, reason);
2399
+ await this.engine.closeSession(authenticationToken, deleteSubscriptions, reason);
2401
2400
  }
2402
2401
  /**
2403
2402
  * @method _on_CloseSessionRequest
@@ -2405,9 +2404,7 @@ export class OPCUAServer extends OPCUABaseServer {
2405
2404
  * @param channel
2406
2405
  * @private
2407
2406
  */
2408
- protected _on_CloseSessionRequest(message: Message, channel: ServerSecureChannelLayer) {
2409
- const server = this;
2410
-
2407
+ protected _on_CloseSessionRequest(message: Message, channel: ServerSecureChannelLayer): void {
2411
2408
  const request = message.request as CloseSessionRequest;
2412
2409
  assert(request instanceof CloseSessionRequest);
2413
2410
 
@@ -2454,8 +2451,7 @@ export class OPCUAServer extends OPCUABaseServer {
2454
2451
  * @param channel
2455
2452
  * @private
2456
2453
  */
2457
- protected _on_BrowseRequest(message: Message, channel: ServerSecureChannelLayer) {
2458
- const server = this;
2454
+ protected _on_BrowseRequest(message: Message, channel: ServerSecureChannelLayer): void {
2459
2455
  const request = message.request as BrowseRequest;
2460
2456
  assert(request instanceof BrowseRequest);
2461
2457
  const diagnostic: any = {};
@@ -2468,7 +2464,7 @@ export class OPCUAServer extends OPCUABaseServer {
2468
2464
  let response: BrowseResponse;
2469
2465
  // test view
2470
2466
  if (request.view && !request.view.viewId.isEmpty()) {
2471
- let theView: UAView | null = server.engine!.addressSpace!.findNode(request.view.viewId) as UAView;
2467
+ let theView: UAView | null = this.engine!.addressSpace!.findNode(request.view.viewId) as UAView;
2472
2468
  if (theView && theView.nodeClass !== NodeClass.View) {
2473
2469
  // Error: theView is not a View
2474
2470
  diagnostic.localizedText = { text: "Expecting a view here" };
@@ -2483,8 +2479,8 @@ export class OPCUAServer extends OPCUABaseServer {
2483
2479
  return sendError(StatusCodes.BadNothingToDo);
2484
2480
  }
2485
2481
 
2486
- if (server.engine.serverCapabilities.operationLimits.maxNodesPerBrowse > 0) {
2487
- if (request.nodesToBrowse.length > server.engine.serverCapabilities.operationLimits.maxNodesPerBrowse) {
2482
+ if (this.engine.serverCapabilities.operationLimits.maxNodesPerBrowse > 0) {
2483
+ if (request.nodesToBrowse.length > this.engine.serverCapabilities.operationLimits.maxNodesPerBrowse) {
2488
2484
  return sendError(StatusCodes.BadTooManyOperations);
2489
2485
  }
2490
2486
  }
@@ -2493,9 +2489,9 @@ export class OPCUAServer extends OPCUABaseServer {
2493
2489
  const requestedMaxReferencesPerNode = Math.min(9876, request.requestedMaxReferencesPerNode);
2494
2490
  assert(request.nodesToBrowse[0].schema.name === "BrowseDescription");
2495
2491
 
2496
- const context = new SessionContext({ session, server });
2492
+ const context = new SessionContext({ session, server: this });
2497
2493
 
2498
- const f = callbackify(server.engine.browseWithAutomaticExpansion).bind(server.engine);
2494
+ const f = callbackify(this.engine.browseWithAutomaticExpansion).bind(this.engine);
2499
2495
  (f as any)(request.nodesToBrowse, context, (err?: Error | null, results?: BrowseResult[]) => {
2500
2496
  // istanbul ignore next
2501
2497
  if (!results) {
@@ -2505,7 +2501,7 @@ export class OPCUAServer extends OPCUABaseServer {
2505
2501
  assert(results[0].schema.name === "BrowseResult");
2506
2502
 
2507
2503
  // handle continuation point and requestedMaxReferencesPerNode
2508
- const maxBrowseContinuationPoints = server.engine.serverCapabilities.maxBrowseContinuationPoints;
2504
+ const maxBrowseContinuationPoints = this.engine.serverCapabilities.maxBrowseContinuationPoints;
2509
2505
  results = results.map((result: BrowseResult) => {
2510
2506
  assert(!result.continuationPoint);
2511
2507
 
@@ -2514,16 +2510,22 @@ export class OPCUAServer extends OPCUABaseServer {
2514
2510
  return new BrowseResult({ statusCode: StatusCodes.BadNoContinuationPoints });
2515
2511
  }
2516
2512
 
2517
- if (session.continuationPointManager.hasReachMaximum(maxBrowseContinuationPoints)) {
2513
+ if (session.continuationPointManager.hasReachedMaximum(maxBrowseContinuationPoints)) {
2518
2514
  return new BrowseResult({ statusCode: StatusCodes.BadNoContinuationPoints });
2519
2515
  }
2520
- const truncatedResult = session.continuationPointManager.register(
2516
+ const truncatedResult = session.continuationPointManager.registerReferences(
2521
2517
  requestedMaxReferencesPerNode,
2522
- result.references || []
2518
+ result.references || [],
2519
+ { continuationPoint: null }
2523
2520
  );
2524
- assert(truncatedResult.statusCode === StatusCodes.Good);
2525
- truncatedResult.statusCode = result.statusCode;
2526
- return new BrowseResult(truncatedResult);
2521
+ let { statusCode } = truncatedResult;
2522
+ const { continuationPoint, values } = truncatedResult;
2523
+ statusCode = result.statusCode;
2524
+ return new BrowseResult({
2525
+ statusCode,
2526
+ continuationPoint,
2527
+ references: values
2528
+ });
2527
2529
  });
2528
2530
 
2529
2531
  response = new BrowseResponse({
@@ -2542,7 +2544,7 @@ export class OPCUAServer extends OPCUABaseServer {
2542
2544
  * @param channel
2543
2545
  * @private
2544
2546
  */
2545
- protected _on_BrowseNextRequest(message: Message, channel: ServerSecureChannelLayer) {
2547
+ protected _on_BrowseNextRequest(message: Message, channel: ServerSecureChannelLayer): void {
2546
2548
  const request = message.request as BrowseNextRequest;
2547
2549
  assert(request instanceof BrowseNextRequest);
2548
2550
  this._apply_on_SessionObject(
@@ -2550,35 +2552,27 @@ export class OPCUAServer extends OPCUABaseServer {
2550
2552
  message,
2551
2553
  channel,
2552
2554
  (session: ServerSession, sendResponse: (response: Response) => void, sendError: (statusCode: StatusCode) => void) => {
2553
- let response;
2554
-
2555
2555
  if (!request.continuationPoints || request.continuationPoints.length === 0) {
2556
2556
  return sendError(StatusCodes.BadNothingToDo);
2557
2557
  }
2558
+ const results = request.continuationPoints
2559
+ .map((continuationPoint: ContinuationPoint, index: number) =>
2560
+ session.continuationPointManager.getNextReferences(0, {
2561
+ continuationPoint,
2562
+ index,
2563
+ releaseContinuationPoints: request.releaseContinuationPoints
2564
+ })
2565
+ )
2566
+ .map(
2567
+ (r) =>
2568
+ <BrowseResultOptions>{
2569
+ continuationPoint: r.continuationPoint,
2570
+ references: r.values,
2571
+ statusCode: r.statusCode
2572
+ }
2573
+ );
2558
2574
 
2559
- // A Boolean parameter with the following values:
2560
-
2561
- let results;
2562
- if (request.releaseContinuationPoints) {
2563
- // releaseContinuationPoints = TRUE
2564
- // passed continuationPoints shall be reset to free resources in
2565
- // the Server. The continuation points are released and the results
2566
- // and diagnosticInfos arrays are empty.
2567
- results = request.continuationPoints.map((continuationPoint: ContinuationPoint) => {
2568
- return session.continuationPointManager.cancel(continuationPoint);
2569
- });
2570
- } else {
2571
- // let extract data from continuation points
2572
-
2573
- // releaseContinuationPoints = FALSE
2574
- // passed continuationPoints shall be used to get the next set of
2575
- // browse information.
2576
- results = request.continuationPoints.map((continuationPoint: ContinuationPoint) => {
2577
- return session.continuationPointManager.getNext(continuationPoint);
2578
- });
2579
- }
2580
-
2581
- response = new BrowseNextResponse({
2575
+ const response = new BrowseNextResponse({
2582
2576
  diagnosticInfos: undefined,
2583
2577
  results
2584
2578
  });
@@ -2588,8 +2582,7 @@ export class OPCUAServer extends OPCUABaseServer {
2588
2582
  }
2589
2583
 
2590
2584
  // read services
2591
- protected _on_ReadRequest(message: Message, channel: ServerSecureChannelLayer) {
2592
- const server = this;
2585
+ protected _on_ReadRequest(message: Message, channel: ServerSecureChannelLayer): void {
2593
2586
  const request = message.request as ReadRequest;
2594
2587
  assert(request instanceof ReadRequest);
2595
2588
 
@@ -2598,7 +2591,7 @@ export class OPCUAServer extends OPCUABaseServer {
2598
2591
  message,
2599
2592
  channel,
2600
2593
  (session: ServerSession, sendResponse: (response: Response) => void, sendError: (statusCode: StatusCode) => void) => {
2601
- const context = new SessionContext({ session, server });
2594
+ const context = new SessionContext({ session, server: this });
2602
2595
 
2603
2596
  let response;
2604
2597
 
@@ -2623,8 +2616,8 @@ export class OPCUAServer extends OPCUABaseServer {
2623
2616
  assert(request.nodesToRead[0].schema.name === "ReadValueId");
2624
2617
 
2625
2618
  // limit size of nodesToRead array to maxNodesPerRead
2626
- if (server.engine.serverCapabilities.operationLimits.maxNodesPerRead > 0) {
2627
- if (request.nodesToRead.length > server.engine.serverCapabilities.operationLimits.maxNodesPerRead) {
2619
+ if (this.engine.serverCapabilities.operationLimits.maxNodesPerRead > 0) {
2620
+ if (request.nodesToRead.length > this.engine.serverCapabilities.operationLimits.maxNodesPerRead) {
2628
2621
  return sendError(StatusCodes.BadTooManyOperations);
2629
2622
  }
2630
2623
  }
@@ -2635,10 +2628,10 @@ export class OPCUAServer extends OPCUABaseServer {
2635
2628
  }
2636
2629
 
2637
2630
  // ask for a refresh of asynchronous variables
2638
- server.engine.refreshValues(request.nodesToRead, request.maxAge, (err?: Error | null) => {
2631
+ this.engine.refreshValues(request.nodesToRead, request.maxAge, (err?: Error | null) => {
2639
2632
  assert(!err, " error not handled here , fix me");
2640
2633
 
2641
- results = server.engine.read(context, request);
2634
+ results = this.engine.read(context, request);
2642
2635
 
2643
2636
  assert(results[0].schema.name === "DataValue");
2644
2637
  assert(results.length === request.nodesToRead!.length);
@@ -2657,8 +2650,7 @@ export class OPCUAServer extends OPCUABaseServer {
2657
2650
  }
2658
2651
 
2659
2652
  // read services
2660
- protected _on_HistoryReadRequest(message: Message, channel: ServerSecureChannelLayer) {
2661
- const server = this;
2653
+ protected _on_HistoryReadRequest(message: Message, channel: ServerSecureChannelLayer): void {
2662
2654
  const request = message.request as HistoryReadRequest;
2663
2655
 
2664
2656
  assert(request instanceof HistoryReadRequest);
@@ -2685,32 +2677,30 @@ export class OPCUAServer extends OPCUABaseServer {
2685
2677
  assert(request.nodesToRead[0].schema.name === "HistoryReadValueId");
2686
2678
 
2687
2679
  // limit size of nodesToRead array to maxNodesPerRead
2688
- if (server.engine.serverCapabilities.operationLimits.maxNodesPerRead > 0) {
2689
- if (request.nodesToRead.length > server.engine.serverCapabilities.operationLimits.maxNodesPerRead) {
2680
+ if (this.engine.serverCapabilities.operationLimits.maxNodesPerRead > 0) {
2681
+ if (request.nodesToRead.length > this.engine.serverCapabilities.operationLimits.maxNodesPerRead) {
2690
2682
  return sendError(StatusCodes.BadTooManyOperations);
2691
2683
  }
2692
2684
  }
2693
2685
  // todo : handle
2694
- if (server.engine.serverCapabilities.operationLimits.maxNodesPerHistoryReadData > 0) {
2695
- if (request.nodesToRead.length > server.engine.serverCapabilities.operationLimits.maxNodesPerHistoryReadData) {
2686
+ if (this.engine.serverCapabilities.operationLimits.maxNodesPerHistoryReadData > 0) {
2687
+ if (request.nodesToRead.length > this.engine.serverCapabilities.operationLimits.maxNodesPerHistoryReadData) {
2696
2688
  return sendError(StatusCodes.BadTooManyOperations);
2697
2689
  }
2698
2690
  }
2699
- if (server.engine.serverCapabilities.operationLimits.maxNodesPerHistoryReadEvents > 0) {
2700
- if (
2701
- request.nodesToRead.length > server.engine.serverCapabilities.operationLimits.maxNodesPerHistoryReadEvents
2702
- ) {
2691
+ if (this.engine.serverCapabilities.operationLimits.maxNodesPerHistoryReadEvents > 0) {
2692
+ if (request.nodesToRead.length > this.engine.serverCapabilities.operationLimits.maxNodesPerHistoryReadEvents) {
2703
2693
  return sendError(StatusCodes.BadTooManyOperations);
2704
2694
  }
2705
2695
  }
2706
2696
 
2707
- const context = new SessionContext({ session, server });
2697
+ const context = new SessionContext({ session, server: this });
2708
2698
 
2709
2699
  // ask for a refresh of asynchronous variables
2710
- server.engine.refreshValues(request.nodesToRead, 0, (err?: Error | null) => {
2700
+ this.engine.refreshValues(request.nodesToRead, 0, (err?: Error | null) => {
2711
2701
  assert(!err, " error not handled here , fix me"); // TODO
2712
2702
 
2713
- server.engine.historyRead(context, request, (err1: Error | null, results?: HistoryReadResult[]) => {
2703
+ this.engine.historyRead(context, request, (err1: Error | null, results?: HistoryReadResult[]) => {
2714
2704
  if (err1) {
2715
2705
  return sendError(StatusCodes.BadHistoryOperationInvalid);
2716
2706
  }
@@ -2748,8 +2738,7 @@ export class OPCUAServer extends OPCUABaseServer {
2748
2738
  // In the cases where the Server is able to verify that it has successfully written to the data source,
2749
2739
  // it reports an unconditional success.
2750
2740
  */
2751
- protected _on_WriteRequest(message: Message, channel: ServerSecureChannelLayer) {
2752
- const server = this;
2741
+ protected _on_WriteRequest(message: Message, channel: ServerSecureChannelLayer): void {
2753
2742
  const request = message.request as WriteRequest;
2754
2743
  assert(request instanceof WriteRequest);
2755
2744
  assert(!request.nodesToWrite || Array.isArray(request.nodesToWrite));
@@ -2765,8 +2754,8 @@ export class OPCUAServer extends OPCUABaseServer {
2765
2754
  return sendError(StatusCodes.BadNothingToDo);
2766
2755
  }
2767
2756
 
2768
- if (server.engine.serverCapabilities.operationLimits.maxNodesPerWrite > 0) {
2769
- if (request.nodesToWrite.length > server.engine.serverCapabilities.operationLimits.maxNodesPerWrite) {
2757
+ if (this.engine.serverCapabilities.operationLimits.maxNodesPerWrite > 0) {
2758
+ if (request.nodesToWrite.length > this.engine.serverCapabilities.operationLimits.maxNodesPerWrite) {
2770
2759
  return sendError(StatusCodes.BadTooManyOperations);
2771
2760
  }
2772
2761
  }
@@ -2776,10 +2765,10 @@ export class OPCUAServer extends OPCUABaseServer {
2776
2765
  nodeToWrite.nodeId = session.resolveRegisteredNode(nodeToWrite.nodeId);
2777
2766
  }
2778
2767
 
2779
- const context = new SessionContext({ session, server });
2768
+ const context = new SessionContext({ session, server: this });
2780
2769
 
2781
2770
  assert(request.nodesToWrite[0].schema.name === "WriteValue");
2782
- server.engine.write(context, request.nodesToWrite, (err: Error | null, results?: StatusCode[]) => {
2771
+ this.engine.write(context, request.nodesToWrite, (err: Error | null, results?: StatusCode[]) => {
2783
2772
  assert(!err);
2784
2773
  assert(Array.isArray(results));
2785
2774
  assert(results!.length === request.nodesToWrite!.length);
@@ -2794,9 +2783,8 @@ export class OPCUAServer extends OPCUABaseServer {
2794
2783
  }
2795
2784
 
2796
2785
  // subscription services
2797
- protected _on_CreateSubscriptionRequest(message: Message, channel: ServerSecureChannelLayer) {
2798
- const server = this;
2799
- const engine = server.engine;
2786
+ protected _on_CreateSubscriptionRequest(message: Message, channel: ServerSecureChannelLayer): void {
2787
+ const engine = this.engine;
2800
2788
  const addressSpace = engine.addressSpace!;
2801
2789
 
2802
2790
  const request = message.request as CreateSubscriptionRequest;
@@ -2807,7 +2795,7 @@ export class OPCUAServer extends OPCUABaseServer {
2807
2795
  message,
2808
2796
  channel,
2809
2797
  (session: ServerSession, sendResponse: (response: Response) => void, sendError: (statusCode: StatusCode) => void) => {
2810
- const context = new SessionContext({ session, server });
2798
+ const context = new SessionContext({ session, server: this });
2811
2799
 
2812
2800
  if (session.currentSubscriptionCount >= OPCUAServer.MAX_SUBSCRIPTION) {
2813
2801
  return sendError(StatusCodes.BadTooManySubscriptions);
@@ -2830,8 +2818,7 @@ export class OPCUAServer extends OPCUABaseServer {
2830
2818
  );
2831
2819
  }
2832
2820
 
2833
- protected _on_DeleteSubscriptionsRequest(message: Message, channel: ServerSecureChannelLayer) {
2834
- const server = this;
2821
+ protected _on_DeleteSubscriptionsRequest(message: Message, channel: ServerSecureChannelLayer): void {
2835
2822
  const request = message.request as DeleteSubscriptionsRequest;
2836
2823
  assert(request instanceof DeleteSubscriptionsRequest);
2837
2824
  this._apply_on_SubscriptionIds(
@@ -2839,13 +2826,13 @@ export class OPCUAServer extends OPCUABaseServer {
2839
2826
  message,
2840
2827
  channel,
2841
2828
  async (session: ServerSession, subscriptionId: number) => {
2842
- let subscription = server.engine.findOrphanSubscription(subscriptionId);
2829
+ let subscription = this.engine.findOrphanSubscription(subscriptionId);
2843
2830
  // istanbul ignore next
2844
2831
  if (subscription) {
2845
2832
  warningLog("Deleting an orphan subscription", subscriptionId);
2846
2833
 
2847
2834
  await this._beforeDeleteSubscription(subscription);
2848
- return server.engine.deleteOrphanSubscription(subscription);
2835
+ return this.engine.deleteOrphanSubscription(subscription);
2849
2836
  }
2850
2837
 
2851
2838
  subscription = session.getSubscription(subscriptionId);
@@ -2858,7 +2845,7 @@ export class OPCUAServer extends OPCUABaseServer {
2858
2845
  );
2859
2846
  }
2860
2847
 
2861
- protected _on_TransferSubscriptionsRequest(message: Message, channel: ServerSecureChannelLayer) {
2848
+ protected _on_TransferSubscriptionsRequest(message: Message, channel: ServerSecureChannelLayer): void {
2862
2849
  //
2863
2850
  // sendInitialValue Boolean
2864
2851
  // A Boolean parameter with the following values:
@@ -2870,8 +2857,7 @@ export class OPCUAServer extends OPCUABaseServer {
2870
2857
  // This parameter only applies to MonitoredItems used for monitoring Attribute changes.
2871
2858
  //
2872
2859
 
2873
- const server = this;
2874
- const engine = server.engine;
2860
+ const engine = this.engine;
2875
2861
 
2876
2862
  const request = message.request as TransferSubscriptionsRequest;
2877
2863
  assert(request instanceof TransferSubscriptionsRequest);
@@ -2884,9 +2870,8 @@ export class OPCUAServer extends OPCUABaseServer {
2884
2870
  );
2885
2871
  }
2886
2872
 
2887
- protected _on_CreateMonitoredItemsRequest(message: Message, channel: ServerSecureChannelLayer) {
2888
- const server = this;
2889
- const engine = server.engine;
2873
+ protected _on_CreateMonitoredItemsRequest(message: Message, channel: ServerSecureChannelLayer): void {
2874
+ const engine = this.engine;
2890
2875
  const addressSpace = engine.addressSpace!;
2891
2876
 
2892
2877
  const request = message.request as CreateMonitoredItemsRequest;
@@ -2910,8 +2895,8 @@ export class OPCUAServer extends OPCUABaseServer {
2910
2895
  if (!request.itemsToCreate || request.itemsToCreate.length === 0) {
2911
2896
  return sendError(StatusCodes.BadNothingToDo);
2912
2897
  }
2913
- if (server.engine.serverCapabilities.operationLimits.maxMonitoredItemsPerCall > 0) {
2914
- if (request.itemsToCreate.length > server.engine.serverCapabilities.operationLimits.maxMonitoredItemsPerCall) {
2898
+ if (this.engine.serverCapabilities.operationLimits.maxMonitoredItemsPerCall > 0) {
2899
+ if (request.itemsToCreate.length > this.engine.serverCapabilities.operationLimits.maxMonitoredItemsPerCall) {
2915
2900
  return sendError(StatusCodes.BadTooManyOperations);
2916
2901
  }
2917
2902
  }
@@ -2955,7 +2940,7 @@ export class OPCUAServer extends OPCUABaseServer {
2955
2940
  );
2956
2941
  }
2957
2942
 
2958
- protected _on_ModifySubscriptionRequest(message: Message, channel: ServerSecureChannelLayer) {
2943
+ protected _on_ModifySubscriptionRequest(message: Message, channel: ServerSecureChannelLayer): void {
2959
2944
  const request = message.request as ModifySubscriptionRequest;
2960
2945
  assert(request instanceof ModifySubscriptionRequest);
2961
2946
 
@@ -2982,8 +2967,7 @@ export class OPCUAServer extends OPCUABaseServer {
2982
2967
  );
2983
2968
  }
2984
2969
 
2985
- protected _on_ModifyMonitoredItemsRequest(message: Message, channel: ServerSecureChannelLayer) {
2986
- const server = this;
2970
+ protected _on_ModifyMonitoredItemsRequest(message: Message, channel: ServerSecureChannelLayer): void {
2987
2971
  const request = message.request as ModifyMonitoredItemsRequest;
2988
2972
 
2989
2973
  assert(request instanceof ModifyMonitoredItemsRequest);
@@ -3007,8 +2991,8 @@ export class OPCUAServer extends OPCUABaseServer {
3007
2991
  }
3008
2992
 
3009
2993
  /* istanbul ignore next */
3010
- if (server.engine.serverCapabilities.operationLimits.maxMonitoredItemsPerCall > 0) {
3011
- if (request.itemsToModify.length > server.engine.serverCapabilities.operationLimits.maxMonitoredItemsPerCall) {
2994
+ if (this.engine.serverCapabilities.operationLimits.maxMonitoredItemsPerCall > 0) {
2995
+ if (request.itemsToModify.length > this.engine.serverCapabilities.operationLimits.maxMonitoredItemsPerCall) {
3012
2996
  return sendError(StatusCodes.BadTooManyOperations);
3013
2997
  }
3014
2998
  }
@@ -3039,7 +3023,7 @@ export class OPCUAServer extends OPCUABaseServer {
3039
3023
  );
3040
3024
  }
3041
3025
 
3042
- protected _on_PublishRequest(message: Message, channel: ServerSecureChannelLayer) {
3026
+ protected _on_PublishRequest(message: Message, channel: ServerSecureChannelLayer): void {
3043
3027
  const request = message.request as PublishRequest;
3044
3028
  assert(request instanceof PublishRequest);
3045
3029
 
@@ -3050,14 +3034,14 @@ export class OPCUAServer extends OPCUABaseServer {
3050
3034
  (session: ServerSession, sendResponse: (response: Response) => void, sendError: (statusCode: StatusCode) => void) => {
3051
3035
  assert(session);
3052
3036
  assert(session.publishEngine); // server.publishEngine doesn't exists, OPCUAServer has probably shut down already
3053
- session.publishEngine._on_PublishRequest(request, (request1: any, response: any) => {
3037
+ session.publishEngine._on_PublishRequest(request, (request1: PublishRequest, response: PublishResponse) => {
3054
3038
  sendResponse(response);
3055
3039
  });
3056
3040
  }
3057
3041
  );
3058
3042
  }
3059
3043
 
3060
- protected _on_SetPublishingModeRequest(message: Message, channel: ServerSecureChannelLayer) {
3044
+ protected _on_SetPublishingModeRequest(message: Message, channel: ServerSecureChannelLayer): void {
3061
3045
  const request = message.request as SetPublishingModeRequest;
3062
3046
  assert(request instanceof SetPublishingModeRequest);
3063
3047
  const publishingEnabled = request.publishingEnabled;
@@ -3071,8 +3055,7 @@ export class OPCUAServer extends OPCUABaseServer {
3071
3055
  );
3072
3056
  }
3073
3057
 
3074
- protected _on_DeleteMonitoredItemsRequest(message: Message, channel: ServerSecureChannelLayer) {
3075
- const server = this;
3058
+ protected _on_DeleteMonitoredItemsRequest(message: Message, channel: ServerSecureChannelLayer): void {
3076
3059
  const request = message.request as DeleteMonitoredItemsRequest;
3077
3060
  assert(request instanceof DeleteMonitoredItemsRequest);
3078
3061
 
@@ -3092,10 +3075,8 @@ export class OPCUAServer extends OPCUABaseServer {
3092
3075
  }
3093
3076
 
3094
3077
  /* istanbul ignore next */
3095
- if (server.engine.serverCapabilities.operationLimits.maxMonitoredItemsPerCall > 0) {
3096
- if (
3097
- request.monitoredItemIds.length > server.engine.serverCapabilities.operationLimits.maxMonitoredItemsPerCall
3098
- ) {
3078
+ if (this.engine.serverCapabilities.operationLimits.maxMonitoredItemsPerCall > 0) {
3079
+ if (request.monitoredItemIds.length > this.engine.serverCapabilities.operationLimits.maxMonitoredItemsPerCall) {
3099
3080
  return sendError(StatusCodes.BadTooManyOperations);
3100
3081
  }
3101
3082
  }
@@ -3126,8 +3107,7 @@ export class OPCUAServer extends OPCUABaseServer {
3126
3107
  }
3127
3108
  );
3128
3109
  }
3129
- protected _on_SetTriggeringRequest(message: Message, channel: ServerSecureChannelLayer) {
3130
- const server = this;
3110
+ protected _on_SetTriggeringRequest(message: Message, channel: ServerSecureChannelLayer): void {
3131
3111
  const request = message.request as SetTriggeringRequest;
3132
3112
  assert(request instanceof SetTriggeringRequest);
3133
3113
 
@@ -3152,8 +3132,8 @@ export class OPCUAServer extends OPCUABaseServer {
3152
3132
  *
3153
3133
  */
3154
3134
  const maxElements = (linksToAdd ? linksToAdd.length : 0) + (linksToRemove ? linksToRemove.length : 0);
3155
- if (server.engine.serverCapabilities.operationLimits.maxMonitoredItemsPerCall > 0) {
3156
- if (maxElements > server.engine.serverCapabilities.operationLimits.maxMonitoredItemsPerCall) {
3135
+ if (this.engine.serverCapabilities.operationLimits.maxMonitoredItemsPerCall > 0) {
3136
+ if (maxElements > this.engine.serverCapabilities.operationLimits.maxMonitoredItemsPerCall) {
3157
3137
  return sendError(StatusCodes.BadTooManyOperations);
3158
3138
  }
3159
3139
  }
@@ -3177,13 +3157,13 @@ export class OPCUAServer extends OPCUABaseServer {
3177
3157
  );
3178
3158
  }
3179
3159
 
3180
- protected async _beforeDeleteSubscription(subscription: Subscription) {
3160
+ protected async _beforeDeleteSubscription(subscription: Subscription): Promise<void> {
3181
3161
  if (!this.options.onDeleteMonitoredItem) {
3182
3162
  return;
3183
3163
  }
3184
3164
  await subscription.applyOnMonitoredItem(this.options.onDeleteMonitoredItem.bind(null, subscription) as any);
3185
3165
  }
3186
- protected _on_RepublishRequest(message: Message, channel: ServerSecureChannelLayer) {
3166
+ protected _on_RepublishRequest(message: Message, channel: ServerSecureChannelLayer): void {
3187
3167
  const request = message.request as RepublishRequest;
3188
3168
  assert(request instanceof RepublishRequest);
3189
3169
 
@@ -3225,8 +3205,7 @@ export class OPCUAServer extends OPCUABaseServer {
3225
3205
  // Bad_TooManyOperations
3226
3206
  // Bad_SubscriptionIdInvalid
3227
3207
  // Bad_MonitoringModeInvalid
3228
- protected _on_SetMonitoringModeRequest(message: Message, channel: ServerSecureChannelLayer) {
3229
- const server = this;
3208
+ protected _on_SetMonitoringModeRequest(message: Message, channel: ServerSecureChannelLayer): void {
3230
3209
  const request = message.request as SetMonitoringModeRequest;
3231
3210
  assert(request instanceof SetMonitoringModeRequest);
3232
3211
 
@@ -3246,10 +3225,8 @@ export class OPCUAServer extends OPCUABaseServer {
3246
3225
  }
3247
3226
 
3248
3227
  /* istanbul ignore next */
3249
- if (server.engine.serverCapabilities.operationLimits.maxMonitoredItemsPerCall > 0) {
3250
- if (
3251
- request.monitoredItemIds.length > server.engine.serverCapabilities.operationLimits.maxMonitoredItemsPerCall
3252
- ) {
3228
+ if (this.engine.serverCapabilities.operationLimits.maxMonitoredItemsPerCall > 0) {
3229
+ if (request.monitoredItemIds.length > this.engine.serverCapabilities.operationLimits.maxMonitoredItemsPerCall) {
3253
3230
  return sendError(StatusCodes.BadTooManyOperations);
3254
3231
  }
3255
3232
  }
@@ -3277,10 +3254,9 @@ export class OPCUAServer extends OPCUABaseServer {
3277
3254
  }
3278
3255
 
3279
3256
  // _on_TranslateBrowsePathsToNodeIds service
3280
- protected _on_TranslateBrowsePathsToNodeIdsRequest(message: Message, channel: ServerSecureChannelLayer) {
3257
+ protected _on_TranslateBrowsePathsToNodeIdsRequest(message: Message, channel: ServerSecureChannelLayer): void {
3281
3258
  const request = message.request as TranslateBrowsePathsToNodeIdsRequest;
3282
3259
  assert(request instanceof TranslateBrowsePathsToNodeIdsRequest);
3283
- const server = this;
3284
3260
 
3285
3261
  this._apply_on_SessionObject(
3286
3262
  TranslateBrowsePathsToNodeIdsResponse,
@@ -3294,16 +3270,16 @@ export class OPCUAServer extends OPCUABaseServer {
3294
3270
  if (!request.browsePaths || request.browsePaths.length === 0) {
3295
3271
  return sendError(StatusCodes.BadNothingToDo);
3296
3272
  }
3297
- if (server.engine.serverCapabilities.operationLimits.maxNodesPerTranslateBrowsePathsToNodeIds > 0) {
3273
+ if (this.engine.serverCapabilities.operationLimits.maxNodesPerTranslateBrowsePathsToNodeIds > 0) {
3298
3274
  if (
3299
3275
  request.browsePaths.length >
3300
- server.engine.serverCapabilities.operationLimits.maxNodesPerTranslateBrowsePathsToNodeIds
3276
+ this.engine.serverCapabilities.operationLimits.maxNodesPerTranslateBrowsePathsToNodeIds
3301
3277
  ) {
3302
3278
  return sendError(StatusCodes.BadTooManyOperations);
3303
3279
  }
3304
3280
  }
3305
3281
 
3306
- const browsePathsResults = request.browsePaths.map((browsePath) => server.engine.browsePath(browsePath));
3282
+ const browsePathsResults = request.browsePaths.map((browsePath) => this.engine.browsePath(browsePath));
3307
3283
 
3308
3284
  const response = new TranslateBrowsePathsToNodeIdsResponse({
3309
3285
  diagnosticInfos: null,
@@ -3320,8 +3296,7 @@ export class OPCUAServer extends OPCUABaseServer {
3320
3296
  // Bad_NothingToDo See Table 165 for the description of this result code.
3321
3297
  // Bad_TooManyOperations See Table 165 for the description of this result code.
3322
3298
  //
3323
- protected _on_CallRequest(message: Message, channel: ServerSecureChannelLayer) {
3324
- const server = this;
3299
+ protected _on_CallRequest(message: Message, channel: ServerSecureChannelLayer): void {
3325
3300
  const request = message.request as CallRequest;
3326
3301
  assert(request instanceof CallRequest);
3327
3302
 
@@ -3338,16 +3313,16 @@ export class OPCUAServer extends OPCUABaseServer {
3338
3313
 
3339
3314
  // the MaxNodesPerMethodCall Property indicates the maximum size of the methodsToCall array when
3340
3315
  // a Client calls the Call Service.
3341
- let maxNodesPerMethodCall = server.engine.serverCapabilities.operationLimits.maxNodesPerMethodCall;
3316
+ let maxNodesPerMethodCall = this.engine.serverCapabilities.operationLimits.maxNodesPerMethodCall;
3342
3317
  maxNodesPerMethodCall = maxNodesPerMethodCall <= 0 ? 1000 : maxNodesPerMethodCall;
3343
3318
  if (request.methodsToCall.length > maxNodesPerMethodCall) {
3344
3319
  return sendError(StatusCodes.BadTooManyOperations);
3345
3320
  }
3346
3321
 
3347
3322
  /* jshint validthis: true */
3348
- const addressSpace = server.engine.addressSpace!;
3323
+ const addressSpace = this.engine.addressSpace!;
3349
3324
 
3350
- const context = new SessionContext({ session, server });
3325
+ const context = new SessionContext({ session, server: this });
3351
3326
 
3352
3327
  async.map(
3353
3328
  request.methodsToCall,
@@ -3368,8 +3343,7 @@ export class OPCUAServer extends OPCUABaseServer {
3368
3343
  );
3369
3344
  }
3370
3345
 
3371
- protected _on_RegisterNodesRequest(message: Message, channel: ServerSecureChannelLayer) {
3372
- const server = this;
3346
+ protected _on_RegisterNodesRequest(message: Message, channel: ServerSecureChannelLayer): void {
3373
3347
  const request = message.request as RegisterNodesRequest;
3374
3348
  assert(request instanceof RegisterNodesRequest);
3375
3349
 
@@ -3384,10 +3358,8 @@ export class OPCUAServer extends OPCUABaseServer {
3384
3358
  response = new RegisterNodesResponse({ responseHeader: { serviceResult: StatusCodes.BadNothingToDo } });
3385
3359
  return sendResponse(response);
3386
3360
  }
3387
- if (server.engine.serverCapabilities.operationLimits.maxNodesPerRegisterNodes > 0) {
3388
- if (
3389
- request.nodesToRegister.length > server.engine.serverCapabilities.operationLimits.maxNodesPerRegisterNodes
3390
- ) {
3361
+ if (this.engine.serverCapabilities.operationLimits.maxNodesPerRegisterNodes > 0) {
3362
+ if (request.nodesToRegister.length > this.engine.serverCapabilities.operationLimits.maxNodesPerRegisterNodes) {
3391
3363
  return sendError(StatusCodes.BadTooManyOperations);
3392
3364
  }
3393
3365
  }
@@ -3408,8 +3380,7 @@ export class OPCUAServer extends OPCUABaseServer {
3408
3380
  );
3409
3381
  }
3410
3382
 
3411
- protected _on_UnregisterNodesRequest(message: Message, channel: ServerSecureChannelLayer) {
3412
- const server = this;
3383
+ protected _on_UnregisterNodesRequest(message: Message, channel: ServerSecureChannelLayer): void {
3413
3384
  const request = message.request as UnregisterNodesRequest;
3414
3385
  assert(request instanceof UnregisterNodesRequest);
3415
3386
 
@@ -3427,9 +3398,9 @@ export class OPCUAServer extends OPCUABaseServer {
3427
3398
  return sendResponse(response);
3428
3399
  }
3429
3400
 
3430
- if (server.engine.serverCapabilities.operationLimits.maxNodesPerRegisterNodes > 0) {
3401
+ if (this.engine.serverCapabilities.operationLimits.maxNodesPerRegisterNodes > 0) {
3431
3402
  if (
3432
- request.nodesToUnregister.length > server.engine.serverCapabilities.operationLimits.maxNodesPerRegisterNodes
3403
+ request.nodesToUnregister.length > this.engine.serverCapabilities.operationLimits.maxNodesPerRegisterNodes
3433
3404
  ) {
3434
3405
  return sendError(StatusCodes.BadTooManyOperations);
3435
3406
  }
@@ -3444,7 +3415,7 @@ export class OPCUAServer extends OPCUABaseServer {
3444
3415
  }
3445
3416
 
3446
3417
  /* istanbul ignore next */
3447
- protected _on_Cancel(message: Message, channel: ServerSecureChannelLayer) {
3418
+ protected _on_Cancel(message: Message, channel: ServerSecureChannelLayer): void {
3448
3419
  return g_sendError(channel, message, CancelResponse, StatusCodes.BadServiceUnsupported);
3449
3420
  }
3450
3421
 
@@ -3453,38 +3424,38 @@ export class OPCUAServer extends OPCUABaseServer {
3453
3424
  // Nodes continue to exist in the AddressSpace even if the Client that created them disconnects from the Server.
3454
3425
  //
3455
3426
  /* istanbul ignore next */
3456
- protected _on_AddNodes(message: Message, channel: ServerSecureChannelLayer) {
3427
+ protected _on_AddNodes(message: Message, channel: ServerSecureChannelLayer): void {
3457
3428
  return g_sendError(channel, message, AddNodesResponse, StatusCodes.BadServiceUnsupported);
3458
3429
  }
3459
3430
 
3460
3431
  /* istanbul ignore next */
3461
- protected _on_AddReferences(message: Message, channel: ServerSecureChannelLayer) {
3432
+ protected _on_AddReferences(message: Message, channel: ServerSecureChannelLayer): void {
3462
3433
  return g_sendError(channel, message, AddReferencesResponse, StatusCodes.BadServiceUnsupported);
3463
3434
  }
3464
3435
 
3465
3436
  /* istanbul ignore next */
3466
- protected _on_DeleteNodes(message: Message, channel: ServerSecureChannelLayer) {
3437
+ protected _on_DeleteNodes(message: Message, channel: ServerSecureChannelLayer): void {
3467
3438
  return g_sendError(channel, message, DeleteNodesResponse, StatusCodes.BadServiceUnsupported);
3468
3439
  }
3469
3440
 
3470
3441
  /* istanbul ignore next */
3471
- protected _on_DeleteReferences(message: Message, channel: ServerSecureChannelLayer) {
3442
+ protected _on_DeleteReferences(message: Message, channel: ServerSecureChannelLayer): void {
3472
3443
  return g_sendError(channel, message, DeleteReferencesResponse, StatusCodes.BadServiceUnsupported);
3473
3444
  }
3474
3445
 
3475
3446
  // Query Service
3476
3447
  /* istanbul ignore next */
3477
- protected _on_QueryFirst(message: Message, channel: ServerSecureChannelLayer) {
3448
+ protected _on_QueryFirst(message: Message, channel: ServerSecureChannelLayer): void {
3478
3449
  return g_sendError(channel, message, QueryFirstResponse, StatusCodes.BadServiceUnsupported);
3479
3450
  }
3480
3451
 
3481
3452
  /* istanbul ignore next */
3482
- protected _on_QueryNext(message: Message, channel: ServerSecureChannelLayer) {
3453
+ protected _on_QueryNext(message: Message, channel: ServerSecureChannelLayer): void {
3483
3454
  return g_sendError(channel, message, QueryNextResponse, StatusCodes.BadServiceUnsupported);
3484
3455
  }
3485
3456
 
3486
3457
  /* istanbul ignore next */
3487
- protected _on_HistoryUpdate(message: Message, channel: ServerSecureChannelLayer) {
3458
+ protected _on_HistoryUpdate(message: Message, channel: ServerSecureChannelLayer): void {
3488
3459
  return g_sendError(channel, message, HistoryUpdateResponse, StatusCodes.BadServiceUnsupported);
3489
3460
  }
3490
3461
 
@@ -3522,7 +3493,7 @@ export class OPCUAServer extends OPCUABaseServer {
3522
3493
 
3523
3494
  /* istanbul ignore next */
3524
3495
  if (
3525
- !Object.prototype.hasOwnProperty.call(endpointOptions,"port") ||
3496
+ !Object.prototype.hasOwnProperty.call(endpointOptions, "port") ||
3526
3497
  !isFinite(endpointOptions.port!) ||
3527
3498
  typeof endpointOptions.port !== "number"
3528
3499
  ) {
@@ -3606,7 +3577,7 @@ export interface RaiseEventAuditCreateSessionEventData extends RaiseEventAuditSe
3606
3577
  secureChannelId: PseudoVariantString;
3607
3578
  revisedSessionTimeout: PseudoVariantDuration;
3608
3579
  clientCertificate: PseudoVariantByteString;
3609
- clientCertificateThumbprint: PseudoVariantByteString;
3580
+ clientCertificateThumbprint: PseudoVariantString;
3610
3581
  }
3611
3582
 
3612
3583
  export interface RaiseEventAuditActivateSessionEventData extends RaiseEventAuditSessionEventData {
@@ -3734,8 +3705,6 @@ export interface OPCUAServer extends EventEmitter {
3734
3705
  on(event: string, eventHandler: (...args: [any?, ...any[]]) => void): this;
3735
3706
  }
3736
3707
 
3737
- // tslint:disable:no-var-requires
3738
- const thenify = require("thenify");
3739
3708
  const opts = { multiArgs: false };
3740
3709
  OPCUAServer.prototype.start = thenify.withCallback(OPCUAServer.prototype.start, opts);
3741
3710
  OPCUAServer.prototype.initialize = thenify.withCallback(OPCUAServer.prototype.initialize, opts);