node-opcua-server 2.70.3 → 2.72.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/opcua_server.d.ts +5 -2
- package/dist/opcua_server.js +20 -13
- package/dist/opcua_server.js.map +1 -1
- package/dist/server_capabilities.d.ts +100 -13
- package/dist/server_capabilities.js +59 -76
- package/dist/server_capabilities.js.map +1 -1
- package/dist/server_end_point.js +2 -1
- package/dist/server_end_point.js.map +1 -1
- package/dist/server_engine.d.ts +1 -0
- package/dist/server_engine.js +29 -1
- package/dist/server_engine.js.map +1 -1
- package/dist/server_session.js.map +1 -1
- package/dist/server_subscription.d.ts +22 -2
- package/dist/server_subscription.js +22 -4
- package/dist/server_subscription.js.map +1 -1
- package/package.json +46 -46
- package/source/opcua_server.ts +27 -16
- package/source/server_capabilities.ts +178 -91
- package/source/server_end_point.ts +9 -8
- package/source/server_engine.ts +30 -1
- package/source/server_session.ts +1 -0
- package/source/server_subscription.ts +46 -5
|
@@ -2,8 +2,10 @@
|
|
|
2
2
|
* @module node-opcua-server
|
|
3
3
|
*/
|
|
4
4
|
// tslint:disable:max-classes-per-file
|
|
5
|
-
import {
|
|
5
|
+
import { UInt32 } from "node-opcua-basic-types";
|
|
6
|
+
import { QualifiedName } from "node-opcua-data-model";
|
|
6
7
|
import { SignedSoftwareCertificate } from "node-opcua-types";
|
|
8
|
+
import { OPCUAServer } from "./opcua_server";
|
|
7
9
|
|
|
8
10
|
/**
|
|
9
11
|
*/
|
|
@@ -37,86 +39,162 @@ export class OperationLimits {
|
|
|
37
39
|
public maxNodesPerTranslateBrowsePathsToNodeIds: number;
|
|
38
40
|
|
|
39
41
|
constructor(options: OperationLimitsOptions) {
|
|
40
|
-
/**
|
|
41
|
-
* @property maxNodesPerRead
|
|
42
|
-
* @default 0
|
|
43
|
-
*/
|
|
44
42
|
this.maxNodesPerRead = options.maxNodesPerRead || 0;
|
|
45
|
-
/**
|
|
46
|
-
* @property maxNodesPerWrite
|
|
47
|
-
* @default 0
|
|
48
|
-
*/
|
|
49
43
|
this.maxNodesPerWrite = options.maxNodesPerWrite || 0;
|
|
50
|
-
/**
|
|
51
|
-
* @property maxNodesPerMethodCall
|
|
52
|
-
* @default 0
|
|
53
|
-
*/
|
|
54
44
|
this.maxNodesPerMethodCall = options.maxNodesPerMethodCall || 0;
|
|
55
|
-
/**
|
|
56
|
-
* @property maxNodesPerBrowse
|
|
57
|
-
* @default 0
|
|
58
|
-
*/
|
|
59
45
|
this.maxNodesPerBrowse = options.maxNodesPerBrowse || 0;
|
|
60
|
-
/**
|
|
61
|
-
* @property maxNodesPerRegisterNodes
|
|
62
|
-
* @default 0
|
|
63
|
-
*/
|
|
64
46
|
this.maxNodesPerRegisterNodes = options.maxNodesPerRegisterNodes || 0;
|
|
65
|
-
/**
|
|
66
|
-
* @property maxNodesPerNodeManagement
|
|
67
|
-
* @default 0
|
|
68
|
-
*/
|
|
69
47
|
this.maxNodesPerNodeManagement = options.maxNodesPerNodeManagement || 0;
|
|
70
|
-
/**
|
|
71
|
-
* @property maxMonitoredItemsPerCall
|
|
72
|
-
* @default 0
|
|
73
|
-
*/
|
|
74
48
|
this.maxMonitoredItemsPerCall = options.maxMonitoredItemsPerCall || 0;
|
|
75
|
-
/**
|
|
76
|
-
* @property maxNodesPerHistoryReadData
|
|
77
|
-
*/
|
|
78
49
|
this.maxNodesPerHistoryReadData = options.maxNodesPerHistoryReadData || 0;
|
|
79
|
-
/**
|
|
80
|
-
* @property maxNodesPerHistoryReadEvents
|
|
81
|
-
* @default 0
|
|
82
|
-
*/
|
|
83
50
|
this.maxNodesPerHistoryReadEvents = options.maxNodesPerHistoryReadEvents || 0;
|
|
84
|
-
/**
|
|
85
|
-
* @property maxNodesPerHistoryUpdateData
|
|
86
|
-
* @default 0
|
|
87
|
-
*/
|
|
88
51
|
this.maxNodesPerHistoryUpdateData = options.maxNodesPerHistoryUpdateData || 0;
|
|
89
|
-
/**
|
|
90
|
-
* @property maxNodesPerHistoryUpdateEvents
|
|
91
|
-
* @default 0
|
|
92
|
-
*/
|
|
93
52
|
this.maxNodesPerHistoryUpdateEvents = options.maxNodesPerHistoryUpdateEvents || 0;
|
|
94
|
-
/**
|
|
95
|
-
* @property maxNodesPerTranslateBrowsePathsToNodeIds
|
|
96
|
-
* @default 0
|
|
97
|
-
*/
|
|
98
53
|
this.maxNodesPerTranslateBrowsePathsToNodeIds = options.maxNodesPerTranslateBrowsePathsToNodeIds || 0;
|
|
99
54
|
}
|
|
100
55
|
}
|
|
101
56
|
|
|
102
|
-
export interface
|
|
103
|
-
maxBrowseContinuationPoints
|
|
104
|
-
maxHistoryContinuationPoints
|
|
105
|
-
maxStringLength
|
|
106
|
-
maxArrayLength
|
|
107
|
-
maxByteStringLength
|
|
108
|
-
maxQueryContinuationPoints
|
|
109
|
-
minSupportedSampleRate
|
|
110
|
-
operationLimits
|
|
111
|
-
|
|
112
|
-
serverProfileArray
|
|
113
|
-
localeIdArray
|
|
114
|
-
softwareCertificates
|
|
57
|
+
export interface IServerCapabilities {
|
|
58
|
+
maxBrowseContinuationPoints: number;
|
|
59
|
+
maxHistoryContinuationPoints: number;
|
|
60
|
+
maxStringLength: number;
|
|
61
|
+
maxArrayLength: number;
|
|
62
|
+
maxByteStringLength: number;
|
|
63
|
+
maxQueryContinuationPoints: number;
|
|
64
|
+
minSupportedSampleRate: number;
|
|
65
|
+
operationLimits: OperationLimitsOptions;
|
|
66
|
+
|
|
67
|
+
serverProfileArray: string[];
|
|
68
|
+
localeIdArray: string[];
|
|
69
|
+
softwareCertificates: SignedSoftwareCertificate[];
|
|
70
|
+
|
|
71
|
+
// new in 1.05
|
|
72
|
+
/**
|
|
73
|
+
* MaxSessions is an integer specifying the maximum number of concurrent
|
|
74
|
+
* Sessions the Server can support. The value specifies the
|
|
75
|
+
* maximum the Server can support under normal circumstances,
|
|
76
|
+
* therefore there is no guarantee the Server can always support
|
|
77
|
+
* the maximum.
|
|
78
|
+
*/
|
|
79
|
+
maxSessions: UInt32;
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* MaxSubscriptions is an integer specifying the maximum number of
|
|
83
|
+
* Subscriptions the Server can support. The value specifies the
|
|
84
|
+
* maximum the Server can support under normal circumstances,
|
|
85
|
+
* therefore there is no guarantee the Server can always support
|
|
86
|
+
* the maximum.
|
|
87
|
+
*/
|
|
88
|
+
maxSubscriptions: UInt32;
|
|
89
|
+
|
|
90
|
+
/**
|
|
91
|
+
* MaxMonitoredItems is an integer specifying the maximum number of
|
|
92
|
+
* MonitoredItems the Server can support. The value specifies the
|
|
93
|
+
* maximum the Server can support under normal circumstances,
|
|
94
|
+
* therefore there is no guarantee the Server can always support
|
|
95
|
+
* the maximum.
|
|
96
|
+
*/
|
|
97
|
+
maxMonitoredItems: UInt32;
|
|
98
|
+
|
|
99
|
+
/**
|
|
100
|
+
* MaxSubscriptionsPerSession is an integer specifying the maximum number of
|
|
101
|
+
* Subscriptions per Session the Server can support. The value specifies the
|
|
102
|
+
* maximum the Server can support under normal circumstances,
|
|
103
|
+
* therefore there is no guarantee the Server can always support
|
|
104
|
+
* the maximum.
|
|
105
|
+
*/
|
|
106
|
+
maxSubscriptionsPerSession: UInt32;
|
|
107
|
+
|
|
108
|
+
/**
|
|
109
|
+
* MaxMonitoredItemsPerSubscription is an integer specifying the maximum number of
|
|
110
|
+
* MonitoredItems per Subscription the Server can support. The value specifies the
|
|
111
|
+
* maximum the Server can support under normal circumstances,
|
|
112
|
+
* therefore there is no guarantee the Server can always support
|
|
113
|
+
* the maximum
|
|
114
|
+
*/
|
|
115
|
+
maxMonitoredItemsPerSubscription: UInt32;
|
|
116
|
+
|
|
117
|
+
/**
|
|
118
|
+
* MaxSelectClauseParameters is an integer specifying the maximum number of
|
|
119
|
+
* EventField SelectClause Parameters the Server can support for an EventFilter.
|
|
120
|
+
* The value specifies the maximum the Server can support under normal circumstances,
|
|
121
|
+
* therefore there is no guarantee the Server can always support
|
|
122
|
+
* the maximum.
|
|
123
|
+
*/
|
|
124
|
+
maxSelectClauseParameters: UInt32;
|
|
125
|
+
|
|
126
|
+
/**
|
|
127
|
+
* MaxWhereClauseParameters is an integer specifying the maximum number of
|
|
128
|
+
* EventField WhereClause Parameters the Server can support for an EventFilter.
|
|
129
|
+
* The value specifies the maximum the Server can support under normal circumstances,
|
|
130
|
+
* therefore there is no guarantee the Server can always support the maximum
|
|
131
|
+
*/
|
|
132
|
+
maxWhereClauseParameters: UInt32;
|
|
133
|
+
|
|
134
|
+
/**
|
|
135
|
+
* (draft)
|
|
136
|
+
* MaxMonitoredItemsQueueSize is an integer specifying the maximum size of MonitoredItem
|
|
137
|
+
* queues. The value specifies the maximum the Server can support under normal circumstances,
|
|
138
|
+
* therefore there is no guarantee the Server can always support the maximum.
|
|
139
|
+
*
|
|
140
|
+
*/
|
|
141
|
+
maxMonitoredItemsQueueSize: UInt32;
|
|
142
|
+
|
|
143
|
+
/**
|
|
144
|
+
*
|
|
145
|
+
* ConformanceUnits is a QualifiedName array specifying the set of conformance units
|
|
146
|
+
* the Server supports. This list should be limited to the ConformanceUnits the Server
|
|
147
|
+
* supports in its current configuration.
|
|
148
|
+
*
|
|
149
|
+
*/
|
|
150
|
+
conformanceUnits: QualifiedName[];
|
|
115
151
|
}
|
|
152
|
+
export type ServerCapabilitiesOptions = Partial<IServerCapabilities>;
|
|
153
|
+
|
|
154
|
+
export const defaultServerCapabilities: IServerCapabilities = {
|
|
155
|
+
maxBrowseContinuationPoints: 0,
|
|
156
|
+
maxHistoryContinuationPoints: 0,
|
|
157
|
+
maxStringLength: 65535,
|
|
158
|
+
maxArrayLength: 65535,
|
|
159
|
+
maxByteStringLength: 65535,
|
|
160
|
+
maxQueryContinuationPoints: 0,
|
|
161
|
+
|
|
162
|
+
minSupportedSampleRate: 100,
|
|
163
|
+
|
|
164
|
+
operationLimits: {
|
|
165
|
+
maxNodesPerBrowse: 0,
|
|
166
|
+
maxNodesPerHistoryReadData: 0,
|
|
167
|
+
maxNodesPerHistoryReadEvents: 0,
|
|
168
|
+
maxNodesPerHistoryUpdateData: 0,
|
|
169
|
+
maxNodesPerHistoryUpdateEvents: 0,
|
|
170
|
+
maxNodesPerMethodCall: 0,
|
|
171
|
+
maxNodesPerNodeManagement: 0,
|
|
172
|
+
maxNodesPerRead: 0,
|
|
173
|
+
maxNodesPerRegisterNodes: 0,
|
|
174
|
+
maxNodesPerWrite: 0,
|
|
175
|
+
maxNodesPerTranslateBrowsePathsToNodeIds: 0,
|
|
176
|
+
maxMonitoredItemsPerCall: 0
|
|
177
|
+
},
|
|
178
|
+
|
|
179
|
+
serverProfileArray: [],
|
|
180
|
+
localeIdArray: [],
|
|
181
|
+
softwareCertificates: [],
|
|
182
|
+
|
|
183
|
+
maxSessions: 10,
|
|
184
|
+
maxSubscriptions: 100,
|
|
185
|
+
maxMonitoredItems: 1000000, // 1 million
|
|
186
|
+
maxSubscriptionsPerSession: 10,
|
|
187
|
+
maxMonitoredItemsPerSubscription: 100000, // one hundred thousand
|
|
188
|
+
maxSelectClauseParameters: 100,
|
|
189
|
+
maxWhereClauseParameters: 100,
|
|
190
|
+
maxMonitoredItemsQueueSize: 60000,
|
|
191
|
+
|
|
192
|
+
conformanceUnits: []
|
|
193
|
+
};
|
|
116
194
|
|
|
117
195
|
/**
|
|
118
196
|
*/
|
|
119
|
-
export class ServerCapabilities {
|
|
197
|
+
export class ServerCapabilities implements IServerCapabilities {
|
|
120
198
|
public maxBrowseContinuationPoints: number;
|
|
121
199
|
public maxHistoryContinuationPoints: number;
|
|
122
200
|
public maxStringLength: number;
|
|
@@ -130,6 +208,18 @@ export class ServerCapabilities {
|
|
|
130
208
|
public localeIdArray: string[];
|
|
131
209
|
public softwareCertificates: SignedSoftwareCertificate[];
|
|
132
210
|
|
|
211
|
+
// new in 1.05
|
|
212
|
+
public maxSessions: UInt32;
|
|
213
|
+
public maxSubscriptions: UInt32;
|
|
214
|
+
public maxMonitoredItems: UInt32;
|
|
215
|
+
public maxSubscriptionsPerSession: UInt32;
|
|
216
|
+
public maxMonitoredItemsPerSubscription: UInt32;
|
|
217
|
+
public maxSelectClauseParameters: UInt32;
|
|
218
|
+
public maxWhereClauseParameters: UInt32;
|
|
219
|
+
public maxMonitoredItemsQueueSize: UInt32;
|
|
220
|
+
public conformanceUnits: QualifiedName[];
|
|
221
|
+
|
|
222
|
+
// eslint-disable-next-line complexity
|
|
133
223
|
constructor(options: ServerCapabilitiesOptions) {
|
|
134
224
|
options = options || {};
|
|
135
225
|
options.operationLimits = options.operationLimits || {};
|
|
@@ -137,36 +227,33 @@ export class ServerCapabilities {
|
|
|
137
227
|
this.serverProfileArray = options.serverProfileArray || [];
|
|
138
228
|
this.localeIdArray = options.localeIdArray || [];
|
|
139
229
|
this.softwareCertificates = options.softwareCertificates || [];
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
this.
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
this.maxByteStringLength = options.maxByteStringLength || 0;
|
|
152
|
-
/**
|
|
153
|
-
* @property maxBrowseContinuationPoints
|
|
154
|
-
*/
|
|
155
|
-
this.maxBrowseContinuationPoints = options.maxBrowseContinuationPoints || 0;
|
|
156
|
-
/**
|
|
157
|
-
* @property maxQueryContinuationPoints
|
|
158
|
-
*/
|
|
159
|
-
this.maxQueryContinuationPoints = options.maxQueryContinuationPoints || 0;
|
|
160
|
-
/**
|
|
161
|
-
* @property maxHistoryContinuationPoints
|
|
162
|
-
*/
|
|
163
|
-
this.maxHistoryContinuationPoints = options.maxHistoryContinuationPoints || 0;
|
|
164
|
-
|
|
165
|
-
/**
|
|
166
|
-
* @property operationLimits
|
|
167
|
-
*/
|
|
230
|
+
|
|
231
|
+
this.maxArrayLength = options.maxArrayLength || defaultServerCapabilities.maxArrayLength;
|
|
232
|
+
this.maxStringLength = options.maxStringLength || defaultServerCapabilities.maxStringLength;
|
|
233
|
+
this.maxByteStringLength = options.maxByteStringLength || defaultServerCapabilities.maxByteStringLength;
|
|
234
|
+
this.maxBrowseContinuationPoints =
|
|
235
|
+
options.maxBrowseContinuationPoints || defaultServerCapabilities.maxBrowseContinuationPoints;
|
|
236
|
+
this.maxQueryContinuationPoints =
|
|
237
|
+
options.maxQueryContinuationPoints || defaultServerCapabilities.maxQueryContinuationPoints;
|
|
238
|
+
this.maxHistoryContinuationPoints =
|
|
239
|
+
options.maxHistoryContinuationPoints || defaultServerCapabilities.maxHistoryContinuationPoints;
|
|
240
|
+
|
|
168
241
|
this.operationLimits = new OperationLimits(options.operationLimits);
|
|
169
242
|
|
|
170
|
-
this.minSupportedSampleRate =
|
|
243
|
+
this.minSupportedSampleRate = options.minSupportedSampleRate || defaultServerCapabilities.minSupportedSampleRate; // to do adjust me
|
|
244
|
+
|
|
245
|
+
// new in 1.05
|
|
246
|
+
this.maxSessions = options.maxSessions || defaultServerCapabilities.maxSessions;
|
|
247
|
+
|
|
248
|
+
this.maxSubscriptionsPerSession = options.maxSubscriptionsPerSession || defaultServerCapabilities.maxSubscriptionsPerSession;
|
|
249
|
+
this.maxSubscriptions = options.maxSubscriptions || defaultServerCapabilities.maxSubscriptions;
|
|
250
|
+
this.maxMonitoredItems = options.maxMonitoredItems || defaultServerCapabilities.maxMonitoredItems;
|
|
251
|
+
this.maxMonitoredItemsPerSubscription =
|
|
252
|
+
options.maxMonitoredItemsPerSubscription || defaultServerCapabilities.maxMonitoredItemsPerSubscription;
|
|
253
|
+
this.maxSelectClauseParameters = options.maxSelectClauseParameters || defaultServerCapabilities.maxSelectClauseParameters;
|
|
254
|
+
this.maxWhereClauseParameters = options.maxWhereClauseParameters || defaultServerCapabilities.maxWhereClauseParameters;
|
|
255
|
+
this.maxMonitoredItemsQueueSize =
|
|
256
|
+
options.maxMonitoredItemsQueueSize || defaultServerCapabilities.maxMonitoredItemsQueueSize;
|
|
257
|
+
this.conformanceUnits = options.conformanceUnits || defaultServerCapabilities.conformanceUnits;
|
|
171
258
|
}
|
|
172
259
|
}
|
|
@@ -11,7 +11,7 @@ import * as async from "async";
|
|
|
11
11
|
import { assert } from "node-opcua-assert";
|
|
12
12
|
import { ICertificateManager, OPCUACertificateManager } from "node-opcua-certificate-manager";
|
|
13
13
|
import { Certificate, convertPEMtoDER, makeSHA1Thumbprint, PrivateKeyPEM, split_der } from "node-opcua-crypto";
|
|
14
|
-
import { checkDebugFlag, make_debugLog, make_errorLog } from "node-opcua-debug";
|
|
14
|
+
import { checkDebugFlag, make_debugLog, make_errorLog, make_warningLog } from "node-opcua-debug";
|
|
15
15
|
import { getFullyQualifiedDomainName, resolveFullyQualifiedDomainName } from "node-opcua-hostname";
|
|
16
16
|
import {
|
|
17
17
|
fromURI,
|
|
@@ -32,6 +32,7 @@ import { ISocketData } from "./i_socket_data";
|
|
|
32
32
|
|
|
33
33
|
const debugLog = make_debugLog(__filename);
|
|
34
34
|
const errorLog = make_errorLog(__filename);
|
|
35
|
+
const warningLog = make_warningLog(__filename);
|
|
35
36
|
const doDebug = checkDebugFlag(__filename);
|
|
36
37
|
|
|
37
38
|
const default_transportProfileUri = "http://opcfoundation.org/UA-Profile/Transport/uatcp-uasc-uabinary";
|
|
@@ -704,14 +705,14 @@ export class OPCUAServerEndPoint extends EventEmitter implements ServerSecureCha
|
|
|
704
705
|
|
|
705
706
|
const establish_connection = () => {
|
|
706
707
|
const nbConnections = Object.keys(this._channels).length;
|
|
707
|
-
debugLog(
|
|
708
|
-
" nbConnections ",
|
|
709
|
-
nbConnections,
|
|
710
|
-
" self._server.maxConnections",
|
|
711
|
-
this._server!.maxConnections,
|
|
712
|
-
this.maxConnections
|
|
713
|
-
);
|
|
714
708
|
if (nbConnections >= this.maxConnections) {
|
|
709
|
+
warningLog(
|
|
710
|
+
" nbConnections ",
|
|
711
|
+
nbConnections,
|
|
712
|
+
" self._server.maxConnections",
|
|
713
|
+
this._server!.maxConnections,
|
|
714
|
+
this.maxConnections
|
|
715
|
+
);
|
|
715
716
|
deny_connection();
|
|
716
717
|
return;
|
|
717
718
|
}
|
package/source/server_engine.ts
CHANGED
|
@@ -314,6 +314,7 @@ export class ServerEngine extends EventEmitter {
|
|
|
314
314
|
private _applicationUri: string;
|
|
315
315
|
private _expectedShutdownTime!: Date;
|
|
316
316
|
private _serverStatus: ServerStatusDataType;
|
|
317
|
+
private _globalCounter: { totalMonitoredItemCount: number } = { totalMonitoredItemCount: 0 };
|
|
317
318
|
|
|
318
319
|
constructor(options: ServerEngineOptions) {
|
|
319
320
|
super();
|
|
@@ -964,6 +965,32 @@ export class ServerEngine extends EventEmitter {
|
|
|
964
965
|
return this.serverCapabilities.maxHistoryContinuationPoints;
|
|
965
966
|
});
|
|
966
967
|
|
|
968
|
+
// new in 1.05
|
|
969
|
+
bindStandardScalar(VariableIds.Server_ServerCapabilities_MaxSessions, DataType.UInt32, () => {
|
|
970
|
+
return this.serverCapabilities.maxSessions;
|
|
971
|
+
});
|
|
972
|
+
bindStandardScalar(VariableIds.Server_ServerCapabilities_MaxSubscriptions, DataType.UInt32, () => {
|
|
973
|
+
return this.serverCapabilities.maxSubscriptions;
|
|
974
|
+
});
|
|
975
|
+
bindStandardScalar(VariableIds.Server_ServerCapabilities_MaxMonitoredItems, DataType.UInt32, () => {
|
|
976
|
+
return this.serverCapabilities.maxMonitoredItems;
|
|
977
|
+
});
|
|
978
|
+
bindStandardScalar(VariableIds.Server_ServerCapabilities_MaxSubscriptionsPerSession, DataType.UInt32, () => {
|
|
979
|
+
return this.serverCapabilities.maxSubscriptionsPerSession;
|
|
980
|
+
});
|
|
981
|
+
bindStandardScalar(VariableIds.Server_ServerCapabilities_MaxSelectClauseParameters, DataType.UInt32, () => {
|
|
982
|
+
return this.serverCapabilities.maxSelectClauseParameters;
|
|
983
|
+
});
|
|
984
|
+
bindStandardScalar(VariableIds.Server_ServerCapabilities_MaxWhereClauseParameters, DataType.UInt32, () => {
|
|
985
|
+
return this.serverCapabilities.maxWhereClauseParameters;
|
|
986
|
+
});
|
|
987
|
+
//bindStandardArray(VariableIds.Server_ServerCapabilities_ConformanceUnits, DataType.QualifiedName, () => {
|
|
988
|
+
// return this.serverCapabilities.conformanceUnits;
|
|
989
|
+
//});
|
|
990
|
+
bindStandardScalar(VariableIds.Server_ServerCapabilities_MaxMonitoredItemsPerSubscription, DataType.UInt32, () => {
|
|
991
|
+
return this.serverCapabilities.maxMonitoredItemsPerSubscription;
|
|
992
|
+
});
|
|
993
|
+
|
|
967
994
|
// added by DI : Server-specific period of time in milliseconds until the Server will revoke a lock.
|
|
968
995
|
// TODO bindStandardScalar(VariableIds.Server_ServerCapabilities_MaxInactiveLockTime,
|
|
969
996
|
// TODO DataType.UInt16, function () {
|
|
@@ -2010,7 +2037,9 @@ export class ServerEngine extends EventEmitter {
|
|
|
2010
2037
|
publishingEnabled: request.publishingEnabled,
|
|
2011
2038
|
publishingInterval,
|
|
2012
2039
|
// -------------------
|
|
2013
|
-
sessionId: NodeId.nullNodeId
|
|
2040
|
+
sessionId: NodeId.nullNodeId,
|
|
2041
|
+
globalCounter: this._globalCounter,
|
|
2042
|
+
serverCapabilities: this.serverCapabilities // shared
|
|
2014
2043
|
});
|
|
2015
2044
|
|
|
2016
2045
|
// add subscriptionDiagnostics
|
package/source/server_session.ts
CHANGED
|
@@ -105,6 +105,7 @@ export class ServerSession extends EventEmitter implements ISubscriber, ISession
|
|
|
105
105
|
public nodeId: NodeId;
|
|
106
106
|
public sessionName = "";
|
|
107
107
|
|
|
108
|
+
|
|
108
109
|
public publishEngine: ServerSidePublishEngine;
|
|
109
110
|
public sessionObject: any;
|
|
110
111
|
public readonly creationDate: Date;
|
|
@@ -10,7 +10,7 @@ import { AddressSpace, BaseNode, Duration, UAObjectType } from "node-opcua-addre
|
|
|
10
10
|
import { checkSelectClauses } from "node-opcua-address-space";
|
|
11
11
|
import { SessionContext } from "node-opcua-address-space";
|
|
12
12
|
import { assert } from "node-opcua-assert";
|
|
13
|
-
import { Byte } from "node-opcua-basic-types";
|
|
13
|
+
import { Byte, UInt32 } from "node-opcua-basic-types";
|
|
14
14
|
import { SubscriptionDiagnosticsDataType } from "node-opcua-common";
|
|
15
15
|
import { NodeClass, AttributeIds, isValidDataEncoding } from "node-opcua-data-model";
|
|
16
16
|
import { TimestampsToReturn } from "node-opcua-data-value";
|
|
@@ -312,6 +312,10 @@ function createSubscriptionDiagnostics(subscription: Subscription): Subscription
|
|
|
312
312
|
return subscriptionDiagnostics as SubscriptionDiagnosticsDataTypePriv;
|
|
313
313
|
}
|
|
314
314
|
|
|
315
|
+
interface IGlobalMonitoredItemCounter {
|
|
316
|
+
totalMonitoredItemCount: number;
|
|
317
|
+
}
|
|
318
|
+
|
|
315
319
|
export interface SubscriptionOptions {
|
|
316
320
|
sessionId?: NodeId;
|
|
317
321
|
/**
|
|
@@ -342,6 +346,9 @@ export interface SubscriptionOptions {
|
|
|
342
346
|
* a unique identifier
|
|
343
347
|
*/
|
|
344
348
|
id?: number;
|
|
349
|
+
|
|
350
|
+
serverCapabilities: ServerCapabilitiesPartial;
|
|
351
|
+
globalCounter: IGlobalMonitoredItemCounter;
|
|
345
352
|
}
|
|
346
353
|
|
|
347
354
|
let g_monitoredItemId = Math.ceil(Math.random() * 100000);
|
|
@@ -435,6 +442,11 @@ export interface MonitoredItemBase {
|
|
|
435
442
|
export type CreateMonitoredItemHook = (subscription: Subscription, monitoredItem: MonitoredItemBase) => Promise<StatusCode>;
|
|
436
443
|
export type DeleteMonitoredItemHook = (subscription: Subscription, monitoredItem: MonitoredItemBase) => Promise<StatusCode>;
|
|
437
444
|
|
|
445
|
+
export interface ServerCapabilitiesPartial {
|
|
446
|
+
maxMonitoredItems: UInt32;
|
|
447
|
+
maxMonitoredItemsPerSubscription: UInt32;
|
|
448
|
+
}
|
|
449
|
+
|
|
438
450
|
/**
|
|
439
451
|
* The Subscription class used in the OPCUA server side.
|
|
440
452
|
*/
|
|
@@ -443,7 +455,19 @@ export class Subscription extends EventEmitter {
|
|
|
443
455
|
public static defaultPublishingInterval = 1000; // one second
|
|
444
456
|
public static maximumPublishingInterval: number = 1000 * 60 * 60 * 24 * 15; // 15 days
|
|
445
457
|
public static maxNotificationPerPublishHighLimit = 1000;
|
|
446
|
-
|
|
458
|
+
|
|
459
|
+
/**
|
|
460
|
+
* maximum number of monitored item in a subscription to be used
|
|
461
|
+
* when serverCapacity.maxMonitoredItems and serverCapacity.maxMonitoredItemsPerSubscription are not set.
|
|
462
|
+
*/
|
|
463
|
+
public static defaultMaxMonitoredItemCount = 20000;
|
|
464
|
+
|
|
465
|
+
/**
|
|
466
|
+
* @deprecated use serverCapacity.maxMonitoredItems and serverCapacity.maxMonitoredItemsPerSubscription instead
|
|
467
|
+
*/
|
|
468
|
+
protected static get maxMonitoredItemCount() {
|
|
469
|
+
return Subscription.defaultMaxMonitoredItemCount;
|
|
470
|
+
}
|
|
447
471
|
|
|
448
472
|
public static registry = new ObjectRegistry();
|
|
449
473
|
|
|
@@ -507,6 +531,9 @@ export class Subscription extends EventEmitter {
|
|
|
507
531
|
private timerId: any;
|
|
508
532
|
private _hasUncollectedMonitoredItemNotifications = false;
|
|
509
533
|
|
|
534
|
+
private globalCounter: IGlobalMonitoredItemCounter;
|
|
535
|
+
private serverCapabilities: ServerCapabilitiesPartial;
|
|
536
|
+
|
|
510
537
|
constructor(options: SubscriptionOptions) {
|
|
511
538
|
super();
|
|
512
539
|
|
|
@@ -566,6 +593,12 @@ export class Subscription extends EventEmitter {
|
|
|
566
593
|
this._start_timer();
|
|
567
594
|
|
|
568
595
|
debugLog(chalk.green(`creating subscription ${this.id}`));
|
|
596
|
+
|
|
597
|
+
this.serverCapabilities = options.serverCapabilities;
|
|
598
|
+
this.serverCapabilities.maxMonitoredItems = this.serverCapabilities.maxMonitoredItems || Subscription.defaultMaxMonitoredItemCount;
|
|
599
|
+
this.serverCapabilities.maxMonitoredItemsPerSubscription =
|
|
600
|
+
this.serverCapabilities.maxMonitoredItemsPerSubscription || Subscription.defaultMaxMonitoredItemCount;
|
|
601
|
+
this.globalCounter = options.globalCounter;
|
|
569
602
|
}
|
|
570
603
|
|
|
571
604
|
public getSessionId(): NodeId {
|
|
@@ -968,12 +1001,16 @@ export class Subscription extends EventEmitter {
|
|
|
968
1001
|
if (statusCodeFilter !== StatusCodes.Good) {
|
|
969
1002
|
return handle_error(statusCodeFilter);
|
|
970
1003
|
}
|
|
971
|
-
|
|
972
|
-
// xx var requestedParameters = monitoredItemCreateRequest.requestedParameters;
|
|
1004
|
+
|
|
973
1005
|
// do we have enough room for new monitored items ?
|
|
974
|
-
if (this.monitoredItemCount >=
|
|
1006
|
+
if (this.monitoredItemCount >= this.serverCapabilities.maxMonitoredItemsPerSubscription) {
|
|
1007
|
+
return handle_error(StatusCodes.BadTooManyMonitoredItems);
|
|
1008
|
+
}
|
|
1009
|
+
|
|
1010
|
+
if (this.globalCounter.totalMonitoredItemCount >= this.serverCapabilities.maxMonitoredItems) {
|
|
975
1011
|
return handle_error(StatusCodes.BadTooManyMonitoredItems);
|
|
976
1012
|
}
|
|
1013
|
+
|
|
977
1014
|
const createResult = this._createMonitoredItemStep2(timestampsToReturn, monitoredItemCreateRequest, node);
|
|
978
1015
|
|
|
979
1016
|
assert(createResult.statusCode === StatusCodes.Good);
|
|
@@ -1052,6 +1089,7 @@ export class Subscription extends EventEmitter {
|
|
|
1052
1089
|
this.emit("removeMonitoredItem", monitoredItem);
|
|
1053
1090
|
|
|
1054
1091
|
delete this.monitoredItems[monitoredItemId];
|
|
1092
|
+
this.globalCounter.totalMonitoredItemCount -= 1;
|
|
1055
1093
|
|
|
1056
1094
|
this._removePendingNotificationsFor(monitoredItemId);
|
|
1057
1095
|
// flush pending notifications
|
|
@@ -1724,7 +1762,10 @@ export class Subscription extends EventEmitter {
|
|
|
1724
1762
|
monitoredItem.$subscription = this;
|
|
1725
1763
|
|
|
1726
1764
|
assert(monitoredItem.monitoredItemId === monitoredItemId);
|
|
1765
|
+
|
|
1727
1766
|
this.monitoredItems[monitoredItemId] = monitoredItem;
|
|
1767
|
+
this.globalCounter.totalMonitoredItemCount += 1;
|
|
1768
|
+
|
|
1728
1769
|
assert(monitoredItem.clientHandle !== 4294967295);
|
|
1729
1770
|
|
|
1730
1771
|
const filterResult = _process_filter(node, requestedParameters.filter);
|