node-opcua-server 2.72.2 → 2.74.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 (42) hide show
  1. package/LICENSE +3 -1
  2. package/dist/helper.d.ts +10 -0
  3. package/dist/helper.js +76 -0
  4. package/dist/helper.js.map +1 -0
  5. package/dist/index.d.ts +1 -0
  6. package/dist/index.js +1 -0
  7. package/dist/index.js.map +1 -1
  8. package/dist/monitored_item.js +2 -1
  9. package/dist/monitored_item.js.map +1 -1
  10. package/dist/opcua_server.js +26 -22
  11. package/dist/opcua_server.js.map +1 -1
  12. package/dist/server_capabilities.js +5 -4
  13. package/dist/server_capabilities.js.map +1 -1
  14. package/dist/server_engine.d.ts +1 -1
  15. package/dist/server_engine.js +25 -25
  16. package/dist/server_engine.js.map +1 -1
  17. package/dist/server_publish_engine.d.ts +6 -5
  18. package/dist/server_publish_engine.js +22 -11
  19. package/dist/server_publish_engine.js.map +1 -1
  20. package/dist/server_publish_engine_for_orphan_subscriptions.js +3 -1
  21. package/dist/server_publish_engine_for_orphan_subscriptions.js.map +1 -1
  22. package/dist/server_session.d.ts +4 -3
  23. package/dist/server_session.js +7 -6
  24. package/dist/server_session.js.map +1 -1
  25. package/dist/server_subscription.d.ts +8 -2
  26. package/dist/server_subscription.js +75 -62
  27. package/dist/server_subscription.js.map +1 -1
  28. package/dist/sessions_compatible_for_transfer.d.ts +1 -1
  29. package/dist/sessions_compatible_for_transfer.js +3 -0
  30. package/dist/sessions_compatible_for_transfer.js.map +1 -1
  31. package/package.json +48 -47
  32. package/source/helper.ts +87 -0
  33. package/source/index.ts +2 -1
  34. package/source/monitored_item.ts +3 -2
  35. package/source/opcua_server.ts +27 -26
  36. package/source/server_capabilities.ts +5 -4
  37. package/source/server_engine.ts +29 -27
  38. package/source/server_publish_engine.ts +34 -21
  39. package/source/server_publish_engine_for_orphan_subscriptions.ts +6 -1
  40. package/source/server_session.ts +15 -13
  41. package/source/server_subscription.ts +89 -72
  42. package/source/sessions_compatible_for_transfer.ts +5 -1
@@ -1,2 +1,2 @@
1
1
  import { ServerSession } from "./server_session";
2
- export declare function sessionsCompatibleForTransfer(sessionSrc: ServerSession, sessionDest: ServerSession): boolean;
2
+ export declare function sessionsCompatibleForTransfer(sessionSrc: ServerSession | undefined, sessionDest: ServerSession): boolean;
@@ -4,6 +4,9 @@ exports.sessionsCompatibleForTransfer = void 0;
4
4
  const node_opcua_assert_1 = require("node-opcua-assert");
5
5
  const node_opcua_types_1 = require("node-opcua-types");
6
6
  function sessionsCompatibleForTransfer(sessionSrc, sessionDest) {
7
+ if (!sessionSrc) {
8
+ return true;
9
+ }
7
10
  (0, node_opcua_assert_1.assert)(sessionDest);
8
11
  (0, node_opcua_assert_1.assert)(sessionSrc);
9
12
  if (!sessionSrc.userIdentityToken && !sessionDest.userIdentityToken) {
@@ -1 +1 @@
1
- {"version":3,"file":"sessions_compatible_for_transfer.js","sourceRoot":"","sources":["../source/sessions_compatible_for_transfer.ts"],"names":[],"mappings":";;;AAAA,yDAA2C;AAC3C,uDAAuH;AAGvH,SAAgB,6BAA6B,CAAC,UAAyB,EAAE,WAA0B;IAC/F,IAAA,0BAAM,EAAC,WAAW,CAAC,CAAC;IACpB,IAAA,0BAAM,EAAC,UAAU,CAAC,CAAC;IACnB,IAAI,CAAC,UAAU,CAAC,iBAAiB,IAAI,CAAC,WAAW,CAAC,iBAAiB,EAAE;QACjE,OAAO,IAAI,CAAC;KACf;IACD,IAAI,UAAU,CAAC,iBAAiB,YAAY,yCAAsB,EAAE;QAChE,IAAI,CAAC,CAAC,WAAW,CAAC,iBAAiB,YAAY,yCAAsB,CAAC,EAAE;YACpE,OAAO,KAAK,CAAC;SAChB;QACD,OAAO,IAAI,CAAC;KACf;SAAM,IAAI,UAAU,CAAC,iBAAiB,YAAY,wCAAqB,EAAE;QACtE,IAAI,CAAC,CAAC,WAAW,CAAC,iBAAiB,YAAY,wCAAqB,CAAC,EAAE;YACnE,OAAO,KAAK,CAAC;SAChB;QACD,OAAO,UAAU,CAAC,iBAAiB,CAAC,QAAQ,KAAK,WAAW,CAAC,iBAAiB,CAAC,QAAQ,CAAC;KAC3F;IACD,uBAAuB;SAClB,IAAI,UAAU,CAAC,iBAAiB,YAAY,oCAAiB,EAAE;QAChE,IAAI,CAAC,CAAC,WAAW,CAAC,iBAAiB,YAAY,oCAAiB,CAAC,EAAE;YAC/D,OAAO,KAAK,CAAC;SAChB;QACD,OAAO,CACH,UAAU,CAAC,iBAAiB,CAAC,eAAe,CAAC,QAAQ,CAAC,KAAK,CAAC;YAC5D,WAAW,CAAC,iBAAiB,CAAC,eAAe,CAAC,QAAQ,CAAC,KAAK,CAAC,CAChE,CAAC;KACL;SAAM;QACH,MAAM,IAAI,KAAK,CAAC,4BAA4B,CAAC,CAAC;KACjD;AACL,CAAC;AA7BD,sEA6BC"}
1
+ {"version":3,"file":"sessions_compatible_for_transfer.js","sourceRoot":"","sources":["../source/sessions_compatible_for_transfer.ts"],"names":[],"mappings":";;;AAAA,yDAA2C;AAC3C,uDAAuH;AAGvH,SAAgB,6BAA6B,CAAC,UAAqC,EAAE,WAA0B;IAE3G,IAAI,CAAC,UAAU,EAAE;QACb,OAAO,IAAI,CAAC;KACf;IACD,IAAA,0BAAM,EAAC,WAAW,CAAC,CAAC;IACpB,IAAA,0BAAM,EAAC,UAAU,CAAC,CAAC;IACnB,IAAI,CAAC,UAAU,CAAC,iBAAiB,IAAI,CAAC,WAAW,CAAC,iBAAiB,EAAE;QACjE,OAAO,IAAI,CAAC;KACf;IACD,IAAI,UAAU,CAAC,iBAAiB,YAAY,yCAAsB,EAAE;QAChE,IAAI,CAAC,CAAC,WAAW,CAAC,iBAAiB,YAAY,yCAAsB,CAAC,EAAE;YACpE,OAAO,KAAK,CAAC;SAChB;QACD,OAAO,IAAI,CAAC;KACf;SAAM,IAAI,UAAU,CAAC,iBAAiB,YAAY,wCAAqB,EAAE;QACtE,IAAI,CAAC,CAAC,WAAW,CAAC,iBAAiB,YAAY,wCAAqB,CAAC,EAAE;YACnE,OAAO,KAAK,CAAC;SAChB;QACD,OAAO,UAAU,CAAC,iBAAiB,CAAC,QAAQ,KAAK,WAAW,CAAC,iBAAiB,CAAC,QAAQ,CAAC;KAC3F;IACD,uBAAuB;SAClB,IAAI,UAAU,CAAC,iBAAiB,YAAY,oCAAiB,EAAE;QAChE,IAAI,CAAC,CAAC,WAAW,CAAC,iBAAiB,YAAY,oCAAiB,CAAC,EAAE;YAC/D,OAAO,KAAK,CAAC;SAChB;QACD,OAAO,CACH,UAAU,CAAC,iBAAiB,CAAC,eAAe,CAAC,QAAQ,CAAC,KAAK,CAAC;YAC5D,WAAW,CAAC,iBAAiB,CAAC,eAAe,CAAC,QAAQ,CAAC,KAAK,CAAC,CAChE,CAAC;KACL;SAAM;QACH,MAAM,IAAI,KAAK,CAAC,4BAA4B,CAAC,CAAC;KACjD;AACL,CAAC;AAjCD,sEAiCC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "node-opcua-server",
3
- "version": "2.72.2",
3
+ "version": "2.74.0",
4
4
  "description": "pure nodejs OPCUA SDK - module -server",
5
5
  "scripts": {
6
6
  "build": "tsc -b",
@@ -17,55 +17,56 @@
17
17
  "async": "^3.2.4",
18
18
  "dequeue": "^1.0.5",
19
19
  "lodash": "4.17.21",
20
- "node-opcua-address-space": "2.72.2",
21
- "node-opcua-assert": "2.66.0",
22
- "node-opcua-basic-types": "2.72.1",
23
- "node-opcua-certificate-manager": "2.72.1",
24
- "node-opcua-client": "2.72.2",
25
- "node-opcua-client-dynamic-extension-object": "2.72.2",
26
- "node-opcua-common": "2.72.2",
27
- "node-opcua-constants": "2.70.0",
20
+ "node-opcua-address-space": "2.74.0",
21
+ "node-opcua-assert": "2.74.0",
22
+ "node-opcua-basic-types": "2.74.0",
23
+ "node-opcua-binary-stream": "2.74.0",
24
+ "node-opcua-certificate-manager": "2.74.0",
25
+ "node-opcua-client": "2.74.0",
26
+ "node-opcua-client-dynamic-extension-object": "2.74.0",
27
+ "node-opcua-common": "2.74.0",
28
+ "node-opcua-constants": "2.74.0",
28
29
  "node-opcua-crypto": "^1.11.0",
29
- "node-opcua-data-access": "2.72.2",
30
- "node-opcua-data-model": "2.72.1",
31
- "node-opcua-data-value": "2.72.2",
32
- "node-opcua-date-time": "2.71.0",
33
- "node-opcua-debug": "2.71.0",
34
- "node-opcua-enum": "2.71.0",
35
- "node-opcua-extension-object": "2.72.1",
36
- "node-opcua-factory": "2.72.1",
37
- "node-opcua-hostname": "2.67.0",
38
- "node-opcua-nodeid": "2.71.0",
39
- "node-opcua-nodeset-ua": "2.72.2",
40
- "node-opcua-nodesets": "2.71.0",
41
- "node-opcua-numeric-range": "2.72.2",
42
- "node-opcua-object-registry": "2.71.0",
30
+ "node-opcua-data-access": "2.74.0",
31
+ "node-opcua-data-model": "2.74.0",
32
+ "node-opcua-data-value": "2.74.0",
33
+ "node-opcua-date-time": "2.74.0",
34
+ "node-opcua-debug": "2.74.0",
35
+ "node-opcua-enum": "2.74.0",
36
+ "node-opcua-extension-object": "2.74.0",
37
+ "node-opcua-factory": "2.74.0",
38
+ "node-opcua-hostname": "2.74.0",
39
+ "node-opcua-nodeid": "2.74.0",
40
+ "node-opcua-nodeset-ua": "2.74.0",
41
+ "node-opcua-nodesets": "2.74.0",
42
+ "node-opcua-numeric-range": "2.74.0",
43
+ "node-opcua-object-registry": "2.74.0",
43
44
  "node-opcua-pki": "^2.17.0",
44
- "node-opcua-secure-channel": "2.72.2",
45
- "node-opcua-service-browse": "2.72.2",
46
- "node-opcua-service-call": "2.72.2",
47
- "node-opcua-service-discovery": "2.72.2",
48
- "node-opcua-service-endpoints": "2.72.2",
49
- "node-opcua-service-filter": "2.72.2",
50
- "node-opcua-service-history": "2.72.2",
51
- "node-opcua-service-node-management": "2.72.2",
52
- "node-opcua-service-query": "2.72.2",
53
- "node-opcua-service-read": "2.72.2",
54
- "node-opcua-service-register-node": "2.72.2",
55
- "node-opcua-service-secure-channel": "2.72.2",
56
- "node-opcua-service-session": "2.72.2",
57
- "node-opcua-service-subscription": "2.72.2",
58
- "node-opcua-service-translate-browse-path": "2.72.2",
59
- "node-opcua-service-write": "2.72.2",
60
- "node-opcua-status-code": "2.71.0",
61
- "node-opcua-transport": "2.72.2",
62
- "node-opcua-types": "2.72.2",
63
- "node-opcua-utils": "2.71.0",
64
- "node-opcua-variant": "2.72.2"
45
+ "node-opcua-secure-channel": "2.74.0",
46
+ "node-opcua-service-browse": "2.74.0",
47
+ "node-opcua-service-call": "2.74.0",
48
+ "node-opcua-service-discovery": "2.74.0",
49
+ "node-opcua-service-endpoints": "2.74.0",
50
+ "node-opcua-service-filter": "2.74.0",
51
+ "node-opcua-service-history": "2.74.0",
52
+ "node-opcua-service-node-management": "2.74.0",
53
+ "node-opcua-service-query": "2.74.0",
54
+ "node-opcua-service-read": "2.74.0",
55
+ "node-opcua-service-register-node": "2.74.0",
56
+ "node-opcua-service-secure-channel": "2.74.0",
57
+ "node-opcua-service-session": "2.74.0",
58
+ "node-opcua-service-subscription": "2.74.0",
59
+ "node-opcua-service-translate-browse-path": "2.74.0",
60
+ "node-opcua-service-write": "2.74.0",
61
+ "node-opcua-status-code": "2.74.0",
62
+ "node-opcua-transport": "2.74.0",
63
+ "node-opcua-types": "2.74.0",
64
+ "node-opcua-utils": "2.74.0",
65
+ "node-opcua-variant": "2.74.0"
65
66
  },
66
67
  "devDependencies": {
67
- "node-opcua-leak-detector": "2.71.0",
68
- "node-opcua-test-helpers": "2.66.0",
68
+ "node-opcua-leak-detector": "2.74.0",
69
+ "node-opcua-test-helpers": "2.74.0",
69
70
  "should": "^13.2.3",
70
71
  "sinon": "^14.0.0"
71
72
  },
@@ -84,5 +85,5 @@
84
85
  "internet of things"
85
86
  ],
86
87
  "homepage": "http://node-opcua.github.io/",
87
- "gitHead": "07dcdd8e8c7f2b55544c6e23023093e35674829c"
88
+ "gitHead": "003ee041795f3b737afaaef5721045ee31ea9f77"
88
89
  }
@@ -0,0 +1,87 @@
1
+ import * as util from "util";
2
+ import { OPCUAServer } from "./opcua_server";
3
+ import { ServerEngine } from "./server_engine";
4
+ import { ServerSession } from "./server_session";
5
+ import { Subscription, SubscriptionState } from "./server_subscription";
6
+
7
+ const consolelog = (...args: any) => {
8
+ const d = new Date();
9
+ const t = d.toTimeString().split(" ")[0] + "." + d.getMilliseconds().toString().padStart(3, "0");
10
+ console.log.apply(console, [t, ...args]);
11
+ };
12
+ const doDebug = false;
13
+
14
+ /**
15
+ *
16
+ * @private
17
+ */
18
+ export function installSessionLogging(server: OPCUAServer) {
19
+ installSessionLoggingOnEngine(server.engine);
20
+ }
21
+
22
+ const info = (subscription: Subscription) => {
23
+ return util.format(
24
+ subscription.subscriptionId,
25
+ SubscriptionState[subscription.state].padEnd(9),
26
+ subscription.state,
27
+ "kac=",
28
+ subscription.currentKeepAliveCount.toString().padStart(3)+
29
+ "/"+
30
+ subscription.maxKeepAliveCount.toString().padStart(3),
31
+ "ltc=",
32
+ subscription.currentLifetimeCount.toString().padStart(3)+
33
+ "/"+
34
+ subscription.lifeTimeCount.toString().padStart(3),
35
+ "prc=",
36
+ subscription.publishEngine?.pendingPublishRequestCount.toString().padStart(3),
37
+ "pi=",
38
+ subscription.publishingInterval
39
+ );
40
+ };
41
+
42
+ export function installSubscriptionMonitoring(subscription: Subscription) {
43
+ consolelog("new_subscription", subscription.subscriptionId, info(subscription));
44
+ subscription.on("lifeTimeExpired", () => {
45
+ consolelog("lifeTimeExpired".padEnd(45), info(subscription));
46
+ });
47
+ if (true || doDebug) {
48
+ subscription.on("lifeTimeCounterChanged", (ltc: number) => {
49
+ consolelog("subscription lifeTimeCounterChanged".padEnd(45), info(subscription));
50
+ });
51
+ }
52
+ subscription.on("expired", () => {
53
+ consolelog("subscription expired".padEnd(45), info(subscription));
54
+ });
55
+ subscription.on("stateChanged", (state: SubscriptionState) => {
56
+ consolelog("subscription stateChanged".padEnd(45), info(subscription));
57
+ });
58
+ subscription.on("terminate", () => {
59
+ consolelog("subscription terminated".padEnd(45), info(subscription));
60
+ });
61
+ subscription.on("keepalive", () => {
62
+ consolelog("subscription keepalive".padEnd(45), info(subscription));
63
+ });
64
+ }
65
+ export function installSessionLoggingOnEngine(serverEngine: ServerEngine) {
66
+ function on_create_session(session: ServerSession) {
67
+ try {
68
+ session.on("activate_session", function () {
69
+ consolelog("activate_session");
70
+ });
71
+
72
+ session.on("statusChanged", (status) => {
73
+ consolelog("session status changed: ", status);
74
+ });
75
+ session.on("new_subscription", function (subscription) {
76
+ installSubscriptionMonitoring(subscription);
77
+ });
78
+ } catch (err) {
79
+ consolelog((err as any).message);
80
+ }
81
+ }
82
+ serverEngine.on("create_session", on_create_session);
83
+ serverEngine.once("session_closed", function (session) {
84
+ consolelog("session is closed");
85
+ serverEngine.removeListener("create_session", on_create_session);
86
+ });
87
+ }
package/source/index.ts CHANGED
@@ -12,4 +12,5 @@ export * from "./server_capabilities";
12
12
  export * from "./server_engine";
13
13
  export * from "./opcua_server";
14
14
  export * from "./monitored_item";
15
- export * from "./user_manager";
15
+ export * from "./user_manager";
16
+ export * from "./helper";
@@ -25,7 +25,7 @@ import {
25
25
  coerceTimestampsToReturn,
26
26
  sameStatusCode
27
27
  } from "node-opcua-data-value";
28
- import { checkDebugFlag, make_debugLog } from "node-opcua-debug";
28
+ import { checkDebugFlag, make_debugLog, make_warningLog } from "node-opcua-debug";
29
29
  import { ExtensionObject } from "node-opcua-extension-object";
30
30
  import { NodeId } from "node-opcua-nodeid";
31
31
  import { NumericalRange0, NumericRange } from "node-opcua-numeric-range";
@@ -71,6 +71,7 @@ const defaultItemToMonitor: ReadValueIdOptions = new ReadValueId({
71
71
 
72
72
  const debugLog = make_debugLog(__filename);
73
73
  const doDebug = checkDebugFlag(__filename);
74
+ const warningLog = make_warningLog(__filename);
74
75
 
75
76
  function _adjust_sampling_interval(samplingInterval: number, node_minimumSamplingInterval: number): number {
76
77
  assert(typeof node_minimumSamplingInterval === "number", "expecting a number");
@@ -216,7 +217,7 @@ function apply_dataChange_filter(this: MonitoredItem, newDataValue: DataValue, o
216
217
  debugLog("timestampHasChanged ", timestampHasChanged(newDataValue.sourceTimestamp, oldDataValue.sourceTimestamp));
217
218
  }
218
219
  } catch (err) {
219
- console.log(err);
220
+ warningLog(err);
220
221
  }
221
222
  }
222
223
  switch (trigger) {
@@ -145,7 +145,8 @@ import {
145
145
  BuildInfoOptions,
146
146
  MonitoredItemCreateResult,
147
147
  IssuedIdentityToken,
148
- BrowseResultOptions
148
+ BrowseResultOptions,
149
+ ServiceFault
149
150
  } from "node-opcua-types";
150
151
  import { DataType } from "node-opcua-variant";
151
152
  import { VariantArrayType } from "node-opcua-variant";
@@ -184,7 +185,7 @@ const warningLog = make_warningLog(__filename);
184
185
  const default_maxConnectionsPerEndpoint = 10;
185
186
 
186
187
  function g_sendError(channel: ServerSecureChannelLayer, message: Message, ResponseClass: any, statusCode: StatusCode): void {
187
- const response = new ResponseClass({
188
+ const response = new ServiceFault({
188
189
  responseHeader: { serviceResult: statusCode }
189
190
  });
190
191
  return channel.send_response("MSG", response, message);
@@ -203,6 +204,7 @@ const default_build_info: BuildInfoOptions = {
203
204
  const minSessionTimeout = 100; // 100 milliseconds
204
205
  const defaultSessionTimeout = 1000 * 30; // 30 seconds
205
206
  const maxSessionTimeout = 1000 * 60 * 50; // 50 minutes
207
+ let unnamed_session_count = 0;
206
208
 
207
209
  type ResponseClassType =
208
210
  | typeof BrowseResponse
@@ -252,7 +254,7 @@ function moveSessionToChannel(session: ServerSession, channel: ServerSecureChann
252
254
  }
253
255
 
254
256
  async function _attempt_to_close_some_old_unactivated_session(server: OPCUAServer) {
255
- const session = server.engine!.getOldestUnactivatedSession();
257
+ const session = server.engine!.getOldestInactiveSession();
256
258
  if (session) {
257
259
  await server.engine!.closeSession(session.authenticationToken, false, "Forcing");
258
260
  }
@@ -1786,7 +1788,7 @@ export class OPCUAServer extends OPCUABaseServer {
1786
1788
  assert(session.sessionTimeout === revisedSessionTimeout);
1787
1789
 
1788
1790
  session.clientDescription = request.clientDescription;
1789
- session.sessionName = request.sessionName || "<unknown session name>";
1791
+ session.sessionName = request.sessionName || `<unknown session name ${unnamed_session_count++}>`;
1790
1792
 
1791
1793
  // Depending upon on the SecurityPolicy and the SecurityMode of the SecureChannel, the exchange of
1792
1794
  // ApplicationInstanceCertificates and Nonces may be optional and the signatures may be empty. See
@@ -2232,13 +2234,14 @@ export class OPCUAServer extends OPCUABaseServer {
2232
2234
 
2233
2235
  function sendResponse(response1: Response) {
2234
2236
  try {
2235
- assert(response1 instanceof ResponseClass);
2237
+ assert(response1 instanceof ResponseClass || response1 instanceof ServiceFault);
2236
2238
  if (message.session) {
2237
2239
  const counterName = ResponseClass.name.replace("Response", "");
2238
2240
  message.session.incrementRequestTotalCounter(counterName);
2239
2241
  }
2240
2242
  return channel.send_response("MSG", response1, message);
2241
2243
  } catch (err) {
2244
+ warningLog(err);
2242
2245
  // istanbul ignore next
2243
2246
  if (err instanceof Error) {
2244
2247
  // istanbul ignore next
@@ -3069,7 +3072,7 @@ export class OPCUAServer extends OPCUABaseServer {
3069
3072
  (session: ServerSession, sendResponse: (response: Response) => void, sendError: (statusCode: StatusCode) => void) => {
3070
3073
  assert(session);
3071
3074
  assert(session.publishEngine); // server.publishEngine doesn't exists, OPCUAServer has probably shut down already
3072
- session.publishEngine._on_PublishRequest(request, (request1: PublishRequest, response: PublishResponse) => {
3075
+ session.publishEngine._on_PublishRequest(request, (_request1, response) => {
3073
3076
  sendResponse(response);
3074
3077
  });
3075
3078
  }
@@ -3136,7 +3139,7 @@ export class OPCUAServer extends OPCUABaseServer {
3136
3139
 
3137
3140
  sendResponse(response);
3138
3141
  } catch (err) {
3139
- console.log(err);
3142
+ warningLog(err);
3140
3143
  return sendError(StatusCodes.BadInternalError);
3141
3144
  }
3142
3145
  }
@@ -3178,16 +3181,20 @@ export class OPCUAServer extends OPCUABaseServer {
3178
3181
  linksToAdd,
3179
3182
  linksToRemove
3180
3183
  );
3181
- const response = new SetTriggeringResponse({
3182
- responseHeader: { serviceResult: statusCode },
3183
-
3184
- addResults,
3185
- removeResults,
3186
- addDiagnosticInfos: null,
3187
- removeDiagnosticInfos: null
3188
- });
3184
+ if (statusCode !== StatusCodes.Good) {
3185
+ const response = new ServiceFault({ responseHeader: { serviceResult: statusCode } });
3186
+ sendResponse(response);
3187
+ } else {
3188
+ const response = new SetTriggeringResponse({
3189
+ responseHeader: { serviceResult: statusCode },
3189
3190
 
3190
- sendResponse(response);
3191
+ addResults,
3192
+ removeResults,
3193
+ addDiagnosticInfos: null,
3194
+ removeDiagnosticInfos: null
3195
+ });
3196
+ sendResponse(response);
3197
+ }
3191
3198
  }
3192
3199
  );
3193
3200
  }
@@ -3388,11 +3395,8 @@ export class OPCUAServer extends OPCUABaseServer {
3388
3395
  message,
3389
3396
  channel,
3390
3397
  (session: ServerSession, sendResponse: (response: Response) => void, sendError: (statusCode: StatusCode) => void) => {
3391
- let response;
3392
-
3393
3398
  if (!request.nodesToRegister || request.nodesToRegister.length === 0) {
3394
- response = new RegisterNodesResponse({ responseHeader: { serviceResult: StatusCodes.BadNothingToDo } });
3395
- return sendResponse(response);
3399
+ return sendError(StatusCodes.BadNothingToDo);
3396
3400
  }
3397
3401
  if (this.engine.serverCapabilities.operationLimits.maxNodesPerRegisterNodes > 0) {
3398
3402
  if (request.nodesToRegister.length > this.engine.serverCapabilities.operationLimits.maxNodesPerRegisterNodes) {
@@ -3408,7 +3412,7 @@ export class OPCUAServer extends OPCUABaseServer {
3408
3412
  // NodeId from the request.
3409
3413
  const registeredNodeIds = request.nodesToRegister.map((nodeId) => session.registerNode(nodeId));
3410
3414
 
3411
- response = new RegisterNodesResponse({
3415
+ const response = new RegisterNodesResponse({
3412
3416
  registeredNodeIds
3413
3417
  });
3414
3418
  sendResponse(response);
@@ -3425,13 +3429,10 @@ export class OPCUAServer extends OPCUABaseServer {
3425
3429
  message,
3426
3430
  channel,
3427
3431
  (session: ServerSession, sendResponse: (response: Response) => void, sendError: (statusCode: StatusCode) => void) => {
3428
- let response;
3429
-
3430
3432
  request.nodesToUnregister = request.nodesToUnregister || [];
3431
3433
 
3432
3434
  if (!request.nodesToUnregister || request.nodesToUnregister.length === 0) {
3433
- response = new UnregisterNodesResponse({ responseHeader: { serviceResult: StatusCodes.BadNothingToDo } });
3434
- return sendResponse(response);
3435
+ return sendError(StatusCodes.BadNothingToDo);
3435
3436
  }
3436
3437
 
3437
3438
  if (this.engine.serverCapabilities.operationLimits.maxNodesPerRegisterNodes > 0) {
@@ -3444,7 +3445,7 @@ export class OPCUAServer extends OPCUABaseServer {
3444
3445
 
3445
3446
  request.nodesToUnregister.map((nodeId: NodeId) => session.unRegisterNode(nodeId));
3446
3447
 
3447
- response = new UnregisterNodesResponse({});
3448
+ const response = new UnregisterNodesResponse({});
3448
3449
  sendResponse(response);
3449
3450
  }
3450
3451
  );
@@ -154,9 +154,9 @@ export type ServerCapabilitiesOptions = Partial<IServerCapabilities>;
154
154
  export const defaultServerCapabilities: IServerCapabilities = {
155
155
  maxBrowseContinuationPoints: 0,
156
156
  maxHistoryContinuationPoints: 0,
157
- maxStringLength: 65535,
158
- maxArrayLength: 65535,
159
- maxByteStringLength: 65535,
157
+ maxStringLength: 16 * 1024 * 1024,
158
+ maxArrayLength: 1024 * 1024,
159
+ maxByteStringLength: 16 * 1024 * 1024,
160
160
  maxQueryContinuationPoints: 0,
161
161
 
162
162
  minSupportedSampleRate: 100,
@@ -245,7 +245,8 @@ export class ServerCapabilities implements IServerCapabilities {
245
245
  // new in 1.05
246
246
  this.maxSessions = options.maxSessions || defaultServerCapabilities.maxSessions;
247
247
 
248
- this.maxSubscriptionsPerSession = options.maxSubscriptionsPerSession || defaultServerCapabilities.maxSubscriptionsPerSession;
248
+ this.maxSubscriptionsPerSession =
249
+ options.maxSubscriptionsPerSession || defaultServerCapabilities.maxSubscriptionsPerSession;
249
250
  this.maxSubscriptions = options.maxSubscriptions || defaultServerCapabilities.maxSubscriptions;
250
251
  this.maxMonitoredItems = options.maxMonitoredItems || defaultServerCapabilities.maxMonitoredItems;
251
252
  this.maxMonitoredItemsPerSubscription =
@@ -5,7 +5,7 @@ import { EventEmitter } from "events";
5
5
  import * as async from "async";
6
6
  import * as chalk from "chalk";
7
7
  import { assert } from "node-opcua-assert";
8
-
8
+ import { BinaryStream} from "node-opcua-binary-stream";
9
9
  import {
10
10
  addElement,
11
11
  AddressSpace,
@@ -399,6 +399,8 @@ export class ServerEngine extends EventEmitter {
399
399
  Object.values(this._sessions).forEach((session: ServerSession) => {
400
400
  counter += session.currentSubscriptionCount;
401
401
  });
402
+ // we also need to add the orphan subscriptions
403
+ counter += this._orphanPublishEngine ? this._orphanPublishEngine .subscriptions.length : 0;
402
404
  return counter;
403
405
  });
404
406
 
@@ -1007,15 +1009,15 @@ export class ServerEngine extends EventEmitter {
1007
1009
  );
1008
1010
 
1009
1011
  bindStandardScalar(VariableIds.Server_ServerCapabilities_MaxArrayLength, DataType.UInt32, () => {
1010
- return this.serverCapabilities.maxArrayLength;
1012
+ return Math.min(this.serverCapabilities.maxArrayLength, Variant.maxArrayLength);
1011
1013
  });
1012
1014
 
1013
1015
  bindStandardScalar(VariableIds.Server_ServerCapabilities_MaxStringLength, DataType.UInt32, () => {
1014
- return this.serverCapabilities.maxStringLength;
1016
+ return Math.min(this.serverCapabilities.maxStringLength, BinaryStream.maxStringLength);
1015
1017
  });
1016
1018
 
1017
1019
  bindStandardScalar(VariableIds.Server_ServerCapabilities_MaxByteStringLength, DataType.UInt32, () => {
1018
- return this.serverCapabilities.maxByteStringLength;
1020
+ return Math.min(this.serverCapabilities.maxByteStringLength, BinaryStream.maxByteStringLength);
1019
1021
  });
1020
1022
 
1021
1023
  const bindOperationLimits = (operationLimits: OperationLimits) => {
@@ -1598,13 +1600,17 @@ export class ServerEngine extends EventEmitter {
1598
1600
  });
1599
1601
  }
1600
1602
 
1601
- public getOldestUnactivatedSession(): ServerSession | null {
1602
- const tmp = Object.values(this._sessions).filter((session1: ServerSession) => {
1603
- return session1.status === "new";
1604
- });
1603
+ public getOldestInactiveSession(): ServerSession | null {
1604
+ // search screwed or closed session first
1605
+ let tmp = Object.values(this._sessions).filter(
1606
+ (session1: ServerSession) =>
1607
+ session1.status === "screwed" || session1.status === "disposed" || session1.status === "closed"
1608
+ );
1605
1609
  if (tmp.length === 0) {
1606
- return null;
1610
+ // if none available, tap into the session that are not yet activated
1611
+ tmp = Object.values(this._sessions).filter((session1: ServerSession) => session1.status === "new");
1607
1612
  }
1613
+ if (tmp.length === 0) return null;
1608
1614
  let session = tmp[0];
1609
1615
  for (let i = 1; i < tmp.length; i++) {
1610
1616
  const c = tmp[i];
@@ -1812,10 +1818,6 @@ export class ServerEngine extends EventEmitter {
1812
1818
  if (!subscription) {
1813
1819
  return new TransferResult({ statusCode: StatusCodes.BadSubscriptionIdInvalid });
1814
1820
  }
1815
- // istanbul ignore next
1816
- if (!subscription.$session) {
1817
- return new TransferResult({ statusCode: StatusCodes.BadInternalError });
1818
- }
1819
1821
 
1820
1822
  // check that session have same userIdentity
1821
1823
  if (!sessionsCompatibleForTransfer(subscription.$session, session)) {
@@ -1846,9 +1848,11 @@ export class ServerEngine extends EventEmitter {
1846
1848
 
1847
1849
  const nbSubscriptionBefore = session.publishEngine.subscriptionCount;
1848
1850
 
1849
- subscription.$session._unexposeSubscriptionDiagnostics(subscription);
1851
+ if (subscription.$session) {
1852
+ subscription.$session._unexposeSubscriptionDiagnostics(subscription);
1853
+ }
1854
+
1850
1855
  await ServerSidePublishEngine.transferSubscription(subscription, session.publishEngine, sendInitialValues);
1851
-
1852
1856
  subscription.$session = session;
1853
1857
 
1854
1858
  session._exposeSubscriptionDiagnostics(subscription);
@@ -1983,7 +1987,7 @@ export class ServerEngine extends EventEmitter {
1983
1987
  }
1984
1988
 
1985
1989
  private _exposeSubscriptionDiagnostics(subscription: Subscription): void {
1986
- debugLog("ServerEngine#_exposeSubscriptionDiagnostics");
1990
+ debugLog("ServerEngine#_exposeSubscriptionDiagnostics", subscription.subscriptionId);
1987
1991
  const subscriptionDiagnosticsArray = this._getServerSubscriptionDiagnosticsArrayNode();
1988
1992
  const subscriptionDiagnostics = subscription.subscriptionDiagnostics;
1989
1993
  assert((subscriptionDiagnostics as any).$subscription === subscription);
@@ -1995,19 +1999,19 @@ export class ServerEngine extends EventEmitter {
1995
1999
  }
1996
2000
 
1997
2001
  protected _unexposeSubscriptionDiagnostics(subscription: Subscription): void {
1998
- const subscriptionDiagnosticsArray = this._getServerSubscriptionDiagnosticsArrayNode();
2002
+ const serverSubscriptionDiagnosticsArray = this._getServerSubscriptionDiagnosticsArrayNode();
1999
2003
  const subscriptionDiagnostics = subscription.subscriptionDiagnostics;
2000
2004
  assert(subscriptionDiagnostics instanceof SubscriptionDiagnosticsDataType);
2001
- if (subscriptionDiagnostics && subscriptionDiagnosticsArray) {
2002
- const node = (subscriptionDiagnosticsArray as any)[subscription.id];
2003
- removeElement(subscriptionDiagnosticsArray, subscriptionDiagnostics);
2005
+ if (subscriptionDiagnostics && serverSubscriptionDiagnosticsArray) {
2006
+ const node = (serverSubscriptionDiagnosticsArray as any)[subscription.id];
2007
+ removeElement(serverSubscriptionDiagnosticsArray, subscriptionDiagnostics);
2004
2008
  /*assert(
2005
2009
  !(subscriptionDiagnosticsArray as any)[subscription.id],
2006
2010
  " subscription node must have been removed from subscriptionDiagnosticsArray"
2007
2011
  );
2008
2012
  */
2009
2013
  }
2010
- debugLog("ServerEngine#_unexposeSubscriptionDiagnostics");
2014
+ debugLog("ServerEngine#_unexposeSubscriptionDiagnostics", subscription.subscriptionId);
2011
2015
  }
2012
2016
 
2013
2017
  /**
@@ -2200,16 +2204,14 @@ export class ServerEngine extends EventEmitter {
2200
2204
  private _getServerSubscriptionDiagnosticsArrayNode(): UADynamicVariableArray<SubscriptionDiagnosticsDataType> | null {
2201
2205
  // istanbul ignore next
2202
2206
  if (!this.addressSpace) {
2203
- if (doDebug) {
2204
- console.warn("ServerEngine#_getServerSubscriptionDiagnosticsArray : no addressSpace");
2205
- }
2207
+ doDebug && debugLog("ServerEngine#_getServerSubscriptionDiagnosticsArray : no addressSpace");
2208
+
2206
2209
  return null; // no addressSpace
2207
2210
  }
2208
2211
  const subscriptionDiagnosticsType = this.addressSpace.findVariableType("SubscriptionDiagnosticsType");
2209
2212
  if (!subscriptionDiagnosticsType) {
2210
- if (doDebug) {
2211
- console.warn("ServerEngine#_getServerSubscriptionDiagnosticsArray " + ": cannot find SubscriptionDiagnosticsType");
2212
- }
2213
+ doDebug &&
2214
+ debugLog("ServerEngine#_getServerSubscriptionDiagnosticsArray " + ": cannot find SubscriptionDiagnosticsType");
2213
2215
  }
2214
2216
 
2215
2217
  // SubscriptionDiagnosticsArray = i=2290