node-opcua-server 2.71.0 → 2.72.2

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 (65) hide show
  1. package/dist/base_server.d.ts +110 -110
  2. package/dist/base_server.js +473 -473
  3. package/dist/factory.d.ts +12 -12
  4. package/dist/factory.js +23 -23
  5. package/dist/history_server_capabilities.d.ts +35 -35
  6. package/dist/history_server_capabilities.js +43 -43
  7. package/dist/i_channel_data.d.ts +13 -13
  8. package/dist/i_channel_data.js +2 -2
  9. package/dist/i_register_server_manager.d.ts +16 -16
  10. package/dist/i_register_server_manager.js +2 -2
  11. package/dist/i_server_side_publish_engine.d.ts +36 -36
  12. package/dist/i_server_side_publish_engine.js +49 -49
  13. package/dist/i_socket_data.d.ts +11 -11
  14. package/dist/i_socket_data.js +2 -2
  15. package/dist/index.d.ts +15 -15
  16. package/dist/index.js +31 -31
  17. package/dist/monitored_item.d.ts +177 -177
  18. package/dist/monitored_item.js +998 -998
  19. package/dist/node_sampler.d.ts +3 -3
  20. package/dist/node_sampler.js +75 -75
  21. package/dist/opcua_server.d.ts +650 -647
  22. package/dist/opcua_server.js +2392 -2385
  23. package/dist/opcua_server.js.map +1 -1
  24. package/dist/queue.d.ts +11 -11
  25. package/dist/queue.js +71 -71
  26. package/dist/register_server_manager.d.ts +96 -96
  27. package/dist/register_server_manager.js +584 -584
  28. package/dist/register_server_manager_hidden.d.ts +17 -17
  29. package/dist/register_server_manager_hidden.js +27 -27
  30. package/dist/register_server_manager_mdns_only.d.ts +22 -22
  31. package/dist/register_server_manager_mdns_only.js +55 -55
  32. package/dist/server_capabilities.d.ts +148 -61
  33. package/dist/server_capabilities.js +91 -108
  34. package/dist/server_capabilities.js.map +1 -1
  35. package/dist/server_end_point.d.ts +183 -183
  36. package/dist/server_end_point.js +817 -816
  37. package/dist/server_end_point.js.map +1 -1
  38. package/dist/server_engine.d.ts +317 -316
  39. package/dist/server_engine.js +1716 -1688
  40. package/dist/server_engine.js.map +1 -1
  41. package/dist/server_publish_engine.d.ts +112 -112
  42. package/dist/server_publish_engine.js +530 -530
  43. package/dist/server_publish_engine_for_orphan_subscriptions.d.ts +16 -16
  44. package/dist/server_publish_engine_for_orphan_subscriptions.js +49 -49
  45. package/dist/server_session.d.ts +181 -181
  46. package/dist/server_session.js +738 -738
  47. package/dist/server_session.js.map +1 -1
  48. package/dist/server_subscription.d.ts +415 -395
  49. package/dist/server_subscription.js +1334 -1316
  50. package/dist/server_subscription.js.map +1 -1
  51. package/dist/sessions_compatible_for_transfer.d.ts +2 -2
  52. package/dist/sessions_compatible_for_transfer.js +36 -36
  53. package/dist/user_manager.d.ts +32 -32
  54. package/dist/user_manager.js +74 -74
  55. package/dist/user_manager_ua.d.ts +3 -3
  56. package/dist/user_manager_ua.js +39 -39
  57. package/dist/validate_filter.d.ts +5 -5
  58. package/dist/validate_filter.js +60 -60
  59. package/package.json +34 -34
  60. package/source/opcua_server.ts +27 -16
  61. package/source/server_capabilities.ts +178 -91
  62. package/source/server_end_point.ts +9 -8
  63. package/source/server_engine.ts +30 -1
  64. package/source/server_session.ts +1 -0
  65. package/source/server_subscription.ts +46 -5
@@ -1,474 +1,474 @@
1
- "use strict";
2
- var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
- function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
- return new (P || (P = Promise))(function (resolve, reject) {
5
- function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
- function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
- function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
- step((generator = generator.apply(thisArg, _arguments || [])).next());
9
- });
10
- };
11
- Object.defineProperty(exports, "__esModule", { value: true });
12
- exports.OPCUABaseServer = void 0;
13
- /**
14
- * @module node-opcua-server
15
- */
16
- // tslint:disable:no-console
17
- const fs = require("fs");
18
- const path = require("path");
19
- const os = require("os");
20
- const async = require("async");
21
- const chalk = require("chalk");
22
- const global_mutex_1 = require("@ster5/global-mutex");
23
- const node_opcua_assert_1 = require("node-opcua-assert");
24
- const node_opcua_certificate_manager_1 = require("node-opcua-certificate-manager");
25
- const node_opcua_common_1 = require("node-opcua-common");
26
- const node_opcua_data_model_1 = require("node-opcua-data-model");
27
- const node_opcua_date_time_1 = require("node-opcua-date-time");
28
- const node_opcua_debug_1 = require("node-opcua-debug");
29
- const node_opcua_debug_2 = require("node-opcua-debug");
30
- const node_opcua_hostname_1 = require("node-opcua-hostname");
31
- const node_opcua_service_discovery_1 = require("node-opcua-service-discovery");
32
- const node_opcua_service_endpoints_1 = require("node-opcua-service-endpoints");
33
- const node_opcua_service_endpoints_2 = require("node-opcua-service-endpoints");
34
- const node_opcua_service_secure_channel_1 = require("node-opcua-service-secure-channel");
35
- const node_opcua_status_code_1 = require("node-opcua-status-code");
36
- const node_opcua_utils_1 = require("node-opcua-utils");
37
- const node_opcua_client_1 = require("node-opcua-client");
38
- const doDebug = (0, node_opcua_debug_1.checkDebugFlag)(__filename);
39
- const debugLog = (0, node_opcua_debug_1.make_debugLog)(__filename);
40
- const errorLog = (0, node_opcua_debug_1.make_errorLog)(__filename);
41
- const warningLog = errorLog;
42
- function constructFilename(p) {
43
- let filename = path.join(__dirname, "..", p);
44
- if (!fs.existsSync(filename)) {
45
- // try one level up
46
- filename = path.join(__dirname, p);
47
- if (!fs.existsSync(filename)) {
48
- throw new Error("Cannot find filename " + filename + " ( __dirname = " + __dirname);
49
- }
50
- }
51
- return filename;
52
- }
53
- const default_server_info = {
54
- // The globally unique identifier for the application instance. This URI is used as
55
- // ServerUri in Services if the application is a Server.
56
- applicationUri: (0, node_opcua_common_1.makeApplicationUrn)(os.hostname(), "NodeOPCUA-Server"),
57
- // The globally unique identifier for the product.
58
- productUri: "NodeOPCUA-Server",
59
- // A localized descriptive name for the application.
60
- applicationName: { text: "NodeOPCUA", locale: "en" },
61
- applicationType: node_opcua_service_endpoints_1.ApplicationType.Server,
62
- gatewayServerUri: "",
63
- discoveryProfileUri: "",
64
- discoveryUrls: []
65
- };
66
- function cleanupEndpoint(endpoint) {
67
- if (endpoint._on_new_channel) {
68
- (0, node_opcua_assert_1.assert)(typeof endpoint._on_new_channel === "function");
69
- endpoint.removeListener("newChannel", endpoint._on_new_channel);
70
- endpoint._on_new_channel = undefined;
71
- }
72
- if (endpoint._on_close_channel) {
73
- (0, node_opcua_assert_1.assert)(typeof endpoint._on_close_channel === "function");
74
- endpoint.removeListener("closeChannel", endpoint._on_close_channel);
75
- endpoint._on_close_channel = undefined;
76
- }
77
- if (endpoint._on_connectionRefused) {
78
- (0, node_opcua_assert_1.assert)(typeof endpoint._on_connectionRefused === "function");
79
- endpoint.removeListener("connectionRefused", endpoint._on_connectionRefused);
80
- endpoint._on_connectionRefused = undefined;
81
- }
82
- if (endpoint._on_openSecureChannelFailure) {
83
- (0, node_opcua_assert_1.assert)(typeof endpoint._on_openSecureChannelFailure === "function");
84
- endpoint.removeListener("openSecureChannelFailure", endpoint._on_openSecureChannelFailure);
85
- endpoint._on_openSecureChannelFailure = undefined;
86
- }
87
- }
88
- const emptyCallback = () => {
89
- /* empty */
90
- };
91
- /**
92
- * @class OPCUABaseServer
93
- * @constructor
94
- */
95
- class OPCUABaseServer extends node_opcua_common_1.OPCUASecureObject {
96
- constructor(options) {
97
- var _a, _b;
98
- options = options || {};
99
- if (!options.serverCertificateManager) {
100
- options.serverCertificateManager = (0, node_opcua_certificate_manager_1.getDefaultCertificateManager)("PKI");
101
- }
102
- options.privateKeyFile = options.privateKeyFile || options.serverCertificateManager.privateKey;
103
- options.certificateFile =
104
- options.certificateFile || path.join(options.serverCertificateManager.rootDir, "own/certs/certificate.pem");
105
- super(options);
106
- this.serverCertificateManager = options.serverCertificateManager;
107
- this.capabilitiesForMDNS = [];
108
- this.endpoints = [];
109
- this.options = options;
110
- this._preInitTask = [];
111
- const serverInfo = Object.assign(Object.assign({}, default_server_info), options.serverInfo);
112
- serverInfo.applicationName = (0, node_opcua_data_model_1.coerceLocalizedText)(serverInfo.applicationName);
113
- this.serverInfo = new node_opcua_service_endpoints_2.ApplicationDescription(serverInfo);
114
- if (this.serverInfo.applicationName.toString().match(/urn:/)) {
115
- errorLog("[NODE-OPCUA-E06] application name cannot be a urn", this.serverInfo.applicationName.toString());
116
- }
117
- this.serverInfo.applicationName.locale = ((_a = this.serverInfo.applicationName) === null || _a === void 0 ? void 0 : _a.locale) || "en";
118
- if (!((_b = this.serverInfo.applicationName) === null || _b === void 0 ? void 0 : _b.locale)) {
119
- warningLog("[NODE-OPCUA-W24] the server applicationName must have a valid locale : ", this.serverInfo.applicationName.toString());
120
- }
121
- const __applicationUri = serverInfo.applicationUri || "";
122
- this.serverInfo.__defineGetter__("applicationUri", () => (0, node_opcua_hostname_1.resolveFullyQualifiedDomainName)(__applicationUri));
123
- this._preInitTask.push(() => __awaiter(this, void 0, void 0, function* () {
124
- const fqdn = yield (0, node_opcua_hostname_1.extractFullyQualifiedDomainName)();
125
- }));
126
- this._preInitTask.push(() => __awaiter(this, void 0, void 0, function* () {
127
- yield this.initializeCM();
128
- }));
129
- }
130
- /**
131
- * The type of server
132
- */
133
- get serverType() {
134
- return this.serverInfo.applicationType;
135
- }
136
- createDefaultCertificate() {
137
- return __awaiter(this, void 0, void 0, function* () {
138
- if (fs.existsSync(this.certificateFile)) {
139
- return;
140
- }
141
- const lockfile = path.join(this.certificateFile + ".lock");
142
- yield (0, global_mutex_1.withLock)({ lockfile }, () => __awaiter(this, void 0, void 0, function* () {
143
- if (!fs.existsSync(this.certificateFile)) {
144
- const applicationUri = this.serverInfo.applicationUri;
145
- const hostname = (0, node_opcua_hostname_1.getHostname)();
146
- yield this.serverCertificateManager.createSelfSignedCertificate({
147
- applicationUri,
148
- dns: [hostname],
149
- // ip: await getIpAddresses(),
150
- outputFile: this.certificateFile,
151
- subject: (0, node_opcua_certificate_manager_1.makeSubject)(this.serverInfo.applicationName.text, hostname),
152
- startDate: new Date(),
153
- validity: 365 * 10 // 10 years
154
- });
155
- }
156
- }));
157
- });
158
- }
159
- initializeCM() {
160
- return __awaiter(this, void 0, void 0, function* () {
161
- yield this.serverCertificateManager.initialize();
162
- yield this.createDefaultCertificate();
163
- debugLog("privateKey = ", this.privateKeyFile, this.serverCertificateManager.privateKey);
164
- debugLog("certificateFile = ", this.certificateFile);
165
- yield node_opcua_client_1.performCertificateSanityCheck.call(this, "server", this.serverCertificateManager, this.serverInfo.applicationUri);
166
- });
167
- }
168
- /**
169
- * start all registered endPoint, in parallel, and call done when all endPoints are listening.
170
- * @method start
171
- * @async
172
- * @param {callback} done
173
- */
174
- start(done) {
175
- (0, node_opcua_assert_1.assert)(typeof done === "function");
176
- this.startAsync()
177
- .then(() => done(null))
178
- .catch((err) => done(err));
179
- }
180
- performPreInitialization() {
181
- return __awaiter(this, void 0, void 0, function* () {
182
- const tasks = this._preInitTask;
183
- this._preInitTask = [];
184
- for (const task of tasks) {
185
- yield task();
186
- }
187
- });
188
- }
189
- startAsync() {
190
- return __awaiter(this, void 0, void 0, function* () {
191
- yield this.performPreInitialization();
192
- (0, node_opcua_assert_1.assert)(Array.isArray(this.endpoints));
193
- (0, node_opcua_assert_1.assert)(this.endpoints.length > 0, "We need at least one end point");
194
- (0, node_opcua_date_time_1.installPeriodicClockAdjustment)();
195
- // eslint-disable-next-line @typescript-eslint/no-this-alias
196
- const server = this;
197
- const _on_new_channel = function (channel) {
198
- server.emit("newChannel", channel, this);
199
- };
200
- const _on_close_channel = function (channel) {
201
- server.emit("closeChannel", channel, this);
202
- };
203
- const _on_connectionRefused = function (socketData) {
204
- server.emit("connectionRefused", socketData, this);
205
- };
206
- const _on_openSecureChannelFailure = function (socketData, channelData) {
207
- server.emit("openSecureChannelFailure", socketData, channelData, this);
208
- };
209
- const promises = [];
210
- for (const endpoint of this.endpoints) {
211
- (0, node_opcua_assert_1.assert)(!endpoint._on_close_channel);
212
- endpoint._on_new_channel = _on_new_channel;
213
- endpoint.on("newChannel", endpoint._on_new_channel);
214
- endpoint._on_close_channel = _on_close_channel;
215
- endpoint.on("closeChannel", endpoint._on_close_channel);
216
- endpoint._on_connectionRefused = _on_connectionRefused;
217
- endpoint.on("connectionRefused", endpoint._on_connectionRefused);
218
- endpoint._on_openSecureChannelFailure = _on_openSecureChannelFailure;
219
- endpoint.on("openSecureChannelFailure", endpoint._on_openSecureChannelFailure);
220
- promises.push(new Promise((resolve, reject) => endpoint.start((err) => (err ? reject(err) : resolve()))));
221
- }
222
- yield Promise.all(promises);
223
- });
224
- }
225
- /**
226
- * shutdown all server endPoints
227
- * @async
228
- */
229
- shutdown(done) {
230
- (0, node_opcua_assert_1.assert)(typeof done === "function");
231
- (0, node_opcua_date_time_1.uninstallPeriodicClockAdjustment)();
232
- this.serverCertificateManager.dispose().then(() => {
233
- debugLog("OPCUABaseServer#shutdown starting");
234
- async.forEach(this.endpoints, (endpoint, callback) => {
235
- cleanupEndpoint(endpoint);
236
- endpoint.shutdown(callback);
237
- }, (err) => {
238
- debugLog("shutdown completed");
239
- done(err);
240
- });
241
- });
242
- }
243
- shutdownChannels(callback) {
244
- (0, node_opcua_assert_1.assert)(typeof callback === "function");
245
- debugLog("OPCUABaseServer#shutdownChannels");
246
- async.forEach(this.endpoints, (endpoint, inner_callback) => {
247
- debugLog(" shutting down endpoint ", endpoint.endpointDescriptions()[0].endpointUrl);
248
- async.series([
249
- // xx (callback2: (err?: Error| null) => void) => {
250
- // xx endpoint.suspendConnection(callback2);
251
- // xx },
252
- (callback2) => {
253
- endpoint.abruptlyInterruptChannels();
254
- endpoint.shutdown(callback2);
255
- }
256
- // xx (callback2: (err?: Error| null) => void) => {
257
- // xx endpoint.restoreConnection(callback2);
258
- // xx }
259
- ], inner_callback);
260
- }, callback);
261
- }
262
- /**
263
- * @private
264
- */
265
- on_request(message, channel) {
266
- (0, node_opcua_assert_1.assert)(message.request);
267
- (0, node_opcua_assert_1.assert)(message.requestId !== 0);
268
- const request = message.request;
269
- // install channel._on_response so we can intercept its call and emit the "response" event.
270
- if (!channel._on_response) {
271
- channel._on_response = (msg, response1 /*, inner_message: Message*/) => {
272
- this.emit("response", response1, channel);
273
- };
274
- }
275
- // prepare request
276
- this.prepare(message, channel);
277
- if (doDebug) {
278
- debugLog(chalk.green.bold("--------------------------------------------------------"), channel.channelId, request.schema.name);
279
- }
280
- let errMessage;
281
- let response;
282
- this.emit("request", request, channel);
283
- try {
284
- // handler must be named _on_ActionRequest()
285
- const handler = this["_on_" + request.schema.name];
286
- if (typeof handler === "function") {
287
- // eslint-disable-next-line prefer-rest-params
288
- handler.apply(this, arguments);
289
- }
290
- else {
291
- errMessage = "[NODE-OPCUA-W07] Unsupported Service : " + request.schema.name;
292
- warningLog(errMessage);
293
- debugLog(chalk.red.bold(errMessage));
294
- response = makeServiceFault(node_opcua_status_code_1.StatusCodes.BadServiceUnsupported, [errMessage]);
295
- channel.send_response("MSG", response, message, emptyCallback);
296
- }
297
- }
298
- catch (err) {
299
- /* istanbul ignore if */
300
- const errMessage1 = "[NODE-OPCUA-W08] EXCEPTION CAUGHT WHILE PROCESSING REQUEST !! " + request.schema.name;
301
- warningLog(chalk.red.bold(errMessage1));
302
- warningLog(request.toString());
303
- (0, node_opcua_debug_2.displayTraceFromThisProjectOnly)(err);
304
- let additional_messages = [];
305
- additional_messages.push("EXCEPTION CAUGHT WHILE PROCESSING REQUEST !!! " + request.schema.name);
306
- if (err instanceof Error) {
307
- additional_messages.push(err.message);
308
- if (err.stack) {
309
- additional_messages = additional_messages.concat(err.stack.split("\n"));
310
- }
311
- }
312
- response = makeServiceFault(node_opcua_status_code_1.StatusCodes.BadInternalError, additional_messages);
313
- channel.send_response("MSG", response, message, emptyCallback);
314
- }
315
- }
316
- /**
317
- * @private
318
- */
319
- _get_endpoints(endpointUrl) {
320
- let endpoints = [];
321
- for (const endPoint of this.endpoints) {
322
- const ep = endPoint.endpointDescriptions();
323
- const epFiltered = endpointUrl ? ep.filter((e) => (0, node_opcua_utils_1.matchUri)(e.endpointUrl, endpointUrl)) : ep;
324
- endpoints = endpoints.concat(epFiltered);
325
- }
326
- return endpoints;
327
- }
328
- /**
329
- * get one of the possible endpointUrl
330
- */
331
- getEndpointUrl() {
332
- return this._get_endpoints()[0].endpointUrl;
333
- }
334
- getDiscoveryUrls() {
335
- const discoveryUrls = this.endpoints.map((e) => {
336
- return e.endpointDescriptions()[0].endpointUrl;
337
- });
338
- return discoveryUrls;
339
- }
340
- getServers(channel) {
341
- this.serverInfo.discoveryUrls = this.getDiscoveryUrls();
342
- const servers = [this.serverInfo];
343
- return servers;
344
- }
345
- suspendEndPoints(callback) {
346
- /* istanbul ignore next */
347
- if (!callback) {
348
- throw new Error("Internal Error");
349
- }
350
- async.forEach(this.endpoints, (ep, _inner_callback) => {
351
- /* istanbul ignore next */
352
- if (doDebug) {
353
- debugLog("Suspending ", ep.endpointDescriptions()[0].endpointUrl);
354
- }
355
- ep.suspendConnection((err) => {
356
- /* istanbul ignore next */
357
- if (doDebug) {
358
- debugLog("Suspended ", ep.endpointDescriptions()[0].endpointUrl);
359
- }
360
- _inner_callback(err);
361
- });
362
- }, (err) => callback(err));
363
- }
364
- resumeEndPoints(callback) {
365
- async.forEach(this.endpoints, (ep, _inner_callback) => {
366
- ep.restoreConnection(_inner_callback);
367
- }, (err) => callback(err));
368
- }
369
- prepare(message, channel) {
370
- /* empty */
371
- }
372
- /**
373
- * @private
374
- */
375
- _on_GetEndpointsRequest(message, channel) {
376
- const request = message.request;
377
- (0, node_opcua_assert_1.assert)(request.schema.name === "GetEndpointsRequest");
378
- const response = new node_opcua_service_endpoints_1.GetEndpointsResponse({});
379
- response.endpoints = this._get_endpoints(null);
380
- response.endpoints = response.endpoints.filter((endpoint) => !endpoint.restricted);
381
- // apply filters
382
- if (request.profileUris && request.profileUris.length > 0) {
383
- response.endpoints = response.endpoints.filter((endpoint) => {
384
- return request.profileUris.indexOf(endpoint.transportProfileUri) >= 0;
385
- });
386
- }
387
- // adjust locale on ApplicationName to match requested local or provide
388
- // a string with neutral locale (locale === null)
389
- // TODO: find a better way to handle this
390
- response.endpoints.forEach((endpoint) => {
391
- endpoint.server.applicationName.locale = "en-US";
392
- });
393
- channel.send_response("MSG", response, message, emptyCallback);
394
- }
395
- /**
396
- * @private
397
- */
398
- _on_FindServersRequest(message, channel) {
399
- // Release 1.02 13 OPC Unified Architecture, Part 4 :
400
- // This Service can be used without security and it is therefore vulnerable to Denial Of Service (DOS)
401
- // attacks. A Server should minimize the amount of processing required to send the response for this
402
- // Service. This can be achieved by preparing the result in advance. The Server should also add a
403
- // short delay before starting processing of a request during high traffic conditions.
404
- const shortDelay = 100; // milliseconds
405
- setTimeout(() => {
406
- const request = message.request;
407
- (0, node_opcua_assert_1.assert)(request.schema.name === "FindServersRequest");
408
- if (!(request instanceof node_opcua_service_discovery_1.FindServersRequest)) {
409
- throw new Error("Invalid request type");
410
- }
411
- let servers = this.getServers(channel);
412
- // apply filters
413
- // TODO /
414
- if (request.serverUris && request.serverUris.length > 0) {
415
- // A serverUri matches the applicationUri from the ApplicationDescription define
416
- servers = servers.filter((inner_Server) => {
417
- return request.serverUris.indexOf(inner_Server.applicationUri) >= 0;
418
- });
419
- }
420
- function adapt(applicationDescription) {
421
- return new node_opcua_service_endpoints_2.ApplicationDescription({
422
- applicationName: applicationDescription.applicationName,
423
- applicationType: applicationDescription.applicationType,
424
- applicationUri: applicationDescription.applicationUri,
425
- discoveryProfileUri: applicationDescription.discoveryProfileUri,
426
- discoveryUrls: applicationDescription.discoveryUrls,
427
- gatewayServerUri: applicationDescription.gatewayServerUri,
428
- productUri: applicationDescription.productUri
429
- });
430
- }
431
- const response = new node_opcua_service_discovery_1.FindServersResponse({
432
- servers: servers.map(adapt)
433
- });
434
- channel.send_response("MSG", response, message, emptyCallback);
435
- }, shortDelay);
436
- }
437
- /**
438
- * returns a array of currently active channels
439
- */
440
- getChannels() {
441
- let channels = [];
442
- for (const endpoint of this.endpoints) {
443
- const c = endpoint.getChannels();
444
- channels = channels.concat(c);
445
- }
446
- return channels;
447
- }
448
- }
449
- exports.OPCUABaseServer = OPCUABaseServer;
450
- OPCUABaseServer.makeServiceFault = makeServiceFault;
451
- /**
452
- * construct a service Fault response
453
- * @method makeServiceFault
454
- * @param statusCode
455
- * @param messages
456
- */
457
- function makeServiceFault(statusCode, messages) {
458
- const response = new node_opcua_service_secure_channel_1.ServiceFault();
459
- response.responseHeader.serviceResult = statusCode;
460
- // xx response.serviceDiagnostics.push( new DiagnosticInfo({ additionalInfo: messages.join("\n")}));
461
- (0, node_opcua_assert_1.assert)(Array.isArray(messages));
462
- (0, node_opcua_assert_1.assert)(typeof messages[0] === "string");
463
- response.responseHeader.stringTable = messages;
464
- // tslint:disable:no-console
465
- warningLog(chalk.cyan(" messages "), messages.join("\n"));
466
- return response;
467
- }
468
- // tslint:disable:no-var-requires
469
- const thenify = require("thenify");
470
- const opts = { multiArgs: false };
471
- OPCUABaseServer.prototype.resumeEndPoints = thenify.withCallback(OPCUABaseServer.prototype.resumeEndPoints, opts);
472
- OPCUABaseServer.prototype.suspendEndPoints = thenify.withCallback(OPCUABaseServer.prototype.suspendEndPoints, opts);
473
- OPCUABaseServer.prototype.shutdownChannels = thenify.withCallback(OPCUABaseServer.prototype.shutdownChannels, opts);
1
+ "use strict";
2
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
+ return new (P || (P = Promise))(function (resolve, reject) {
5
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
9
+ });
10
+ };
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ exports.OPCUABaseServer = void 0;
13
+ /**
14
+ * @module node-opcua-server
15
+ */
16
+ // tslint:disable:no-console
17
+ const fs = require("fs");
18
+ const path = require("path");
19
+ const os = require("os");
20
+ const async = require("async");
21
+ const chalk = require("chalk");
22
+ const global_mutex_1 = require("@ster5/global-mutex");
23
+ const node_opcua_assert_1 = require("node-opcua-assert");
24
+ const node_opcua_certificate_manager_1 = require("node-opcua-certificate-manager");
25
+ const node_opcua_common_1 = require("node-opcua-common");
26
+ const node_opcua_data_model_1 = require("node-opcua-data-model");
27
+ const node_opcua_date_time_1 = require("node-opcua-date-time");
28
+ const node_opcua_debug_1 = require("node-opcua-debug");
29
+ const node_opcua_debug_2 = require("node-opcua-debug");
30
+ const node_opcua_hostname_1 = require("node-opcua-hostname");
31
+ const node_opcua_service_discovery_1 = require("node-opcua-service-discovery");
32
+ const node_opcua_service_endpoints_1 = require("node-opcua-service-endpoints");
33
+ const node_opcua_service_endpoints_2 = require("node-opcua-service-endpoints");
34
+ const node_opcua_service_secure_channel_1 = require("node-opcua-service-secure-channel");
35
+ const node_opcua_status_code_1 = require("node-opcua-status-code");
36
+ const node_opcua_utils_1 = require("node-opcua-utils");
37
+ const node_opcua_client_1 = require("node-opcua-client");
38
+ const doDebug = (0, node_opcua_debug_1.checkDebugFlag)(__filename);
39
+ const debugLog = (0, node_opcua_debug_1.make_debugLog)(__filename);
40
+ const errorLog = (0, node_opcua_debug_1.make_errorLog)(__filename);
41
+ const warningLog = errorLog;
42
+ function constructFilename(p) {
43
+ let filename = path.join(__dirname, "..", p);
44
+ if (!fs.existsSync(filename)) {
45
+ // try one level up
46
+ filename = path.join(__dirname, p);
47
+ if (!fs.existsSync(filename)) {
48
+ throw new Error("Cannot find filename " + filename + " ( __dirname = " + __dirname);
49
+ }
50
+ }
51
+ return filename;
52
+ }
53
+ const default_server_info = {
54
+ // The globally unique identifier for the application instance. This URI is used as
55
+ // ServerUri in Services if the application is a Server.
56
+ applicationUri: (0, node_opcua_common_1.makeApplicationUrn)(os.hostname(), "NodeOPCUA-Server"),
57
+ // The globally unique identifier for the product.
58
+ productUri: "NodeOPCUA-Server",
59
+ // A localized descriptive name for the application.
60
+ applicationName: { text: "NodeOPCUA", locale: "en" },
61
+ applicationType: node_opcua_service_endpoints_1.ApplicationType.Server,
62
+ gatewayServerUri: "",
63
+ discoveryProfileUri: "",
64
+ discoveryUrls: []
65
+ };
66
+ function cleanupEndpoint(endpoint) {
67
+ if (endpoint._on_new_channel) {
68
+ (0, node_opcua_assert_1.assert)(typeof endpoint._on_new_channel === "function");
69
+ endpoint.removeListener("newChannel", endpoint._on_new_channel);
70
+ endpoint._on_new_channel = undefined;
71
+ }
72
+ if (endpoint._on_close_channel) {
73
+ (0, node_opcua_assert_1.assert)(typeof endpoint._on_close_channel === "function");
74
+ endpoint.removeListener("closeChannel", endpoint._on_close_channel);
75
+ endpoint._on_close_channel = undefined;
76
+ }
77
+ if (endpoint._on_connectionRefused) {
78
+ (0, node_opcua_assert_1.assert)(typeof endpoint._on_connectionRefused === "function");
79
+ endpoint.removeListener("connectionRefused", endpoint._on_connectionRefused);
80
+ endpoint._on_connectionRefused = undefined;
81
+ }
82
+ if (endpoint._on_openSecureChannelFailure) {
83
+ (0, node_opcua_assert_1.assert)(typeof endpoint._on_openSecureChannelFailure === "function");
84
+ endpoint.removeListener("openSecureChannelFailure", endpoint._on_openSecureChannelFailure);
85
+ endpoint._on_openSecureChannelFailure = undefined;
86
+ }
87
+ }
88
+ const emptyCallback = () => {
89
+ /* empty */
90
+ };
91
+ /**
92
+ * @class OPCUABaseServer
93
+ * @constructor
94
+ */
95
+ class OPCUABaseServer extends node_opcua_common_1.OPCUASecureObject {
96
+ constructor(options) {
97
+ var _a, _b;
98
+ options = options || {};
99
+ if (!options.serverCertificateManager) {
100
+ options.serverCertificateManager = (0, node_opcua_certificate_manager_1.getDefaultCertificateManager)("PKI");
101
+ }
102
+ options.privateKeyFile = options.privateKeyFile || options.serverCertificateManager.privateKey;
103
+ options.certificateFile =
104
+ options.certificateFile || path.join(options.serverCertificateManager.rootDir, "own/certs/certificate.pem");
105
+ super(options);
106
+ this.serverCertificateManager = options.serverCertificateManager;
107
+ this.capabilitiesForMDNS = [];
108
+ this.endpoints = [];
109
+ this.options = options;
110
+ this._preInitTask = [];
111
+ const serverInfo = Object.assign(Object.assign({}, default_server_info), options.serverInfo);
112
+ serverInfo.applicationName = (0, node_opcua_data_model_1.coerceLocalizedText)(serverInfo.applicationName);
113
+ this.serverInfo = new node_opcua_service_endpoints_2.ApplicationDescription(serverInfo);
114
+ if (this.serverInfo.applicationName.toString().match(/urn:/)) {
115
+ errorLog("[NODE-OPCUA-E06] application name cannot be a urn", this.serverInfo.applicationName.toString());
116
+ }
117
+ this.serverInfo.applicationName.locale = ((_a = this.serverInfo.applicationName) === null || _a === void 0 ? void 0 : _a.locale) || "en";
118
+ if (!((_b = this.serverInfo.applicationName) === null || _b === void 0 ? void 0 : _b.locale)) {
119
+ warningLog("[NODE-OPCUA-W24] the server applicationName must have a valid locale : ", this.serverInfo.applicationName.toString());
120
+ }
121
+ const __applicationUri = serverInfo.applicationUri || "";
122
+ this.serverInfo.__defineGetter__("applicationUri", () => (0, node_opcua_hostname_1.resolveFullyQualifiedDomainName)(__applicationUri));
123
+ this._preInitTask.push(() => __awaiter(this, void 0, void 0, function* () {
124
+ const fqdn = yield (0, node_opcua_hostname_1.extractFullyQualifiedDomainName)();
125
+ }));
126
+ this._preInitTask.push(() => __awaiter(this, void 0, void 0, function* () {
127
+ yield this.initializeCM();
128
+ }));
129
+ }
130
+ /**
131
+ * The type of server
132
+ */
133
+ get serverType() {
134
+ return this.serverInfo.applicationType;
135
+ }
136
+ createDefaultCertificate() {
137
+ return __awaiter(this, void 0, void 0, function* () {
138
+ if (fs.existsSync(this.certificateFile)) {
139
+ return;
140
+ }
141
+ const lockfile = path.join(this.certificateFile + ".lock");
142
+ yield (0, global_mutex_1.withLock)({ lockfile }, () => __awaiter(this, void 0, void 0, function* () {
143
+ if (!fs.existsSync(this.certificateFile)) {
144
+ const applicationUri = this.serverInfo.applicationUri;
145
+ const hostname = (0, node_opcua_hostname_1.getHostname)();
146
+ yield this.serverCertificateManager.createSelfSignedCertificate({
147
+ applicationUri,
148
+ dns: [hostname],
149
+ // ip: await getIpAddresses(),
150
+ outputFile: this.certificateFile,
151
+ subject: (0, node_opcua_certificate_manager_1.makeSubject)(this.serverInfo.applicationName.text, hostname),
152
+ startDate: new Date(),
153
+ validity: 365 * 10 // 10 years
154
+ });
155
+ }
156
+ }));
157
+ });
158
+ }
159
+ initializeCM() {
160
+ return __awaiter(this, void 0, void 0, function* () {
161
+ yield this.serverCertificateManager.initialize();
162
+ yield this.createDefaultCertificate();
163
+ debugLog("privateKey = ", this.privateKeyFile, this.serverCertificateManager.privateKey);
164
+ debugLog("certificateFile = ", this.certificateFile);
165
+ yield node_opcua_client_1.performCertificateSanityCheck.call(this, "server", this.serverCertificateManager, this.serverInfo.applicationUri);
166
+ });
167
+ }
168
+ /**
169
+ * start all registered endPoint, in parallel, and call done when all endPoints are listening.
170
+ * @method start
171
+ * @async
172
+ * @param {callback} done
173
+ */
174
+ start(done) {
175
+ (0, node_opcua_assert_1.assert)(typeof done === "function");
176
+ this.startAsync()
177
+ .then(() => done(null))
178
+ .catch((err) => done(err));
179
+ }
180
+ performPreInitialization() {
181
+ return __awaiter(this, void 0, void 0, function* () {
182
+ const tasks = this._preInitTask;
183
+ this._preInitTask = [];
184
+ for (const task of tasks) {
185
+ yield task();
186
+ }
187
+ });
188
+ }
189
+ startAsync() {
190
+ return __awaiter(this, void 0, void 0, function* () {
191
+ yield this.performPreInitialization();
192
+ (0, node_opcua_assert_1.assert)(Array.isArray(this.endpoints));
193
+ (0, node_opcua_assert_1.assert)(this.endpoints.length > 0, "We need at least one end point");
194
+ (0, node_opcua_date_time_1.installPeriodicClockAdjustment)();
195
+ // eslint-disable-next-line @typescript-eslint/no-this-alias
196
+ const server = this;
197
+ const _on_new_channel = function (channel) {
198
+ server.emit("newChannel", channel, this);
199
+ };
200
+ const _on_close_channel = function (channel) {
201
+ server.emit("closeChannel", channel, this);
202
+ };
203
+ const _on_connectionRefused = function (socketData) {
204
+ server.emit("connectionRefused", socketData, this);
205
+ };
206
+ const _on_openSecureChannelFailure = function (socketData, channelData) {
207
+ server.emit("openSecureChannelFailure", socketData, channelData, this);
208
+ };
209
+ const promises = [];
210
+ for (const endpoint of this.endpoints) {
211
+ (0, node_opcua_assert_1.assert)(!endpoint._on_close_channel);
212
+ endpoint._on_new_channel = _on_new_channel;
213
+ endpoint.on("newChannel", endpoint._on_new_channel);
214
+ endpoint._on_close_channel = _on_close_channel;
215
+ endpoint.on("closeChannel", endpoint._on_close_channel);
216
+ endpoint._on_connectionRefused = _on_connectionRefused;
217
+ endpoint.on("connectionRefused", endpoint._on_connectionRefused);
218
+ endpoint._on_openSecureChannelFailure = _on_openSecureChannelFailure;
219
+ endpoint.on("openSecureChannelFailure", endpoint._on_openSecureChannelFailure);
220
+ promises.push(new Promise((resolve, reject) => endpoint.start((err) => (err ? reject(err) : resolve()))));
221
+ }
222
+ yield Promise.all(promises);
223
+ });
224
+ }
225
+ /**
226
+ * shutdown all server endPoints
227
+ * @async
228
+ */
229
+ shutdown(done) {
230
+ (0, node_opcua_assert_1.assert)(typeof done === "function");
231
+ (0, node_opcua_date_time_1.uninstallPeriodicClockAdjustment)();
232
+ this.serverCertificateManager.dispose().then(() => {
233
+ debugLog("OPCUABaseServer#shutdown starting");
234
+ async.forEach(this.endpoints, (endpoint, callback) => {
235
+ cleanupEndpoint(endpoint);
236
+ endpoint.shutdown(callback);
237
+ }, (err) => {
238
+ debugLog("shutdown completed");
239
+ done(err);
240
+ });
241
+ });
242
+ }
243
+ shutdownChannels(callback) {
244
+ (0, node_opcua_assert_1.assert)(typeof callback === "function");
245
+ debugLog("OPCUABaseServer#shutdownChannels");
246
+ async.forEach(this.endpoints, (endpoint, inner_callback) => {
247
+ debugLog(" shutting down endpoint ", endpoint.endpointDescriptions()[0].endpointUrl);
248
+ async.series([
249
+ // xx (callback2: (err?: Error| null) => void) => {
250
+ // xx endpoint.suspendConnection(callback2);
251
+ // xx },
252
+ (callback2) => {
253
+ endpoint.abruptlyInterruptChannels();
254
+ endpoint.shutdown(callback2);
255
+ }
256
+ // xx (callback2: (err?: Error| null) => void) => {
257
+ // xx endpoint.restoreConnection(callback2);
258
+ // xx }
259
+ ], inner_callback);
260
+ }, callback);
261
+ }
262
+ /**
263
+ * @private
264
+ */
265
+ on_request(message, channel) {
266
+ (0, node_opcua_assert_1.assert)(message.request);
267
+ (0, node_opcua_assert_1.assert)(message.requestId !== 0);
268
+ const request = message.request;
269
+ // install channel._on_response so we can intercept its call and emit the "response" event.
270
+ if (!channel._on_response) {
271
+ channel._on_response = (msg, response1 /*, inner_message: Message*/) => {
272
+ this.emit("response", response1, channel);
273
+ };
274
+ }
275
+ // prepare request
276
+ this.prepare(message, channel);
277
+ if (doDebug) {
278
+ debugLog(chalk.green.bold("--------------------------------------------------------"), channel.channelId, request.schema.name);
279
+ }
280
+ let errMessage;
281
+ let response;
282
+ this.emit("request", request, channel);
283
+ try {
284
+ // handler must be named _on_ActionRequest()
285
+ const handler = this["_on_" + request.schema.name];
286
+ if (typeof handler === "function") {
287
+ // eslint-disable-next-line prefer-rest-params
288
+ handler.apply(this, arguments);
289
+ }
290
+ else {
291
+ errMessage = "[NODE-OPCUA-W07] Unsupported Service : " + request.schema.name;
292
+ warningLog(errMessage);
293
+ debugLog(chalk.red.bold(errMessage));
294
+ response = makeServiceFault(node_opcua_status_code_1.StatusCodes.BadServiceUnsupported, [errMessage]);
295
+ channel.send_response("MSG", response, message, emptyCallback);
296
+ }
297
+ }
298
+ catch (err) {
299
+ /* istanbul ignore if */
300
+ const errMessage1 = "[NODE-OPCUA-W08] EXCEPTION CAUGHT WHILE PROCESSING REQUEST !! " + request.schema.name;
301
+ warningLog(chalk.red.bold(errMessage1));
302
+ warningLog(request.toString());
303
+ (0, node_opcua_debug_2.displayTraceFromThisProjectOnly)(err);
304
+ let additional_messages = [];
305
+ additional_messages.push("EXCEPTION CAUGHT WHILE PROCESSING REQUEST !!! " + request.schema.name);
306
+ if (err instanceof Error) {
307
+ additional_messages.push(err.message);
308
+ if (err.stack) {
309
+ additional_messages = additional_messages.concat(err.stack.split("\n"));
310
+ }
311
+ }
312
+ response = makeServiceFault(node_opcua_status_code_1.StatusCodes.BadInternalError, additional_messages);
313
+ channel.send_response("MSG", response, message, emptyCallback);
314
+ }
315
+ }
316
+ /**
317
+ * @private
318
+ */
319
+ _get_endpoints(endpointUrl) {
320
+ let endpoints = [];
321
+ for (const endPoint of this.endpoints) {
322
+ const ep = endPoint.endpointDescriptions();
323
+ const epFiltered = endpointUrl ? ep.filter((e) => (0, node_opcua_utils_1.matchUri)(e.endpointUrl, endpointUrl)) : ep;
324
+ endpoints = endpoints.concat(epFiltered);
325
+ }
326
+ return endpoints;
327
+ }
328
+ /**
329
+ * get one of the possible endpointUrl
330
+ */
331
+ getEndpointUrl() {
332
+ return this._get_endpoints()[0].endpointUrl;
333
+ }
334
+ getDiscoveryUrls() {
335
+ const discoveryUrls = this.endpoints.map((e) => {
336
+ return e.endpointDescriptions()[0].endpointUrl;
337
+ });
338
+ return discoveryUrls;
339
+ }
340
+ getServers(channel) {
341
+ this.serverInfo.discoveryUrls = this.getDiscoveryUrls();
342
+ const servers = [this.serverInfo];
343
+ return servers;
344
+ }
345
+ suspendEndPoints(callback) {
346
+ /* istanbul ignore next */
347
+ if (!callback) {
348
+ throw new Error("Internal Error");
349
+ }
350
+ async.forEach(this.endpoints, (ep, _inner_callback) => {
351
+ /* istanbul ignore next */
352
+ if (doDebug) {
353
+ debugLog("Suspending ", ep.endpointDescriptions()[0].endpointUrl);
354
+ }
355
+ ep.suspendConnection((err) => {
356
+ /* istanbul ignore next */
357
+ if (doDebug) {
358
+ debugLog("Suspended ", ep.endpointDescriptions()[0].endpointUrl);
359
+ }
360
+ _inner_callback(err);
361
+ });
362
+ }, (err) => callback(err));
363
+ }
364
+ resumeEndPoints(callback) {
365
+ async.forEach(this.endpoints, (ep, _inner_callback) => {
366
+ ep.restoreConnection(_inner_callback);
367
+ }, (err) => callback(err));
368
+ }
369
+ prepare(message, channel) {
370
+ /* empty */
371
+ }
372
+ /**
373
+ * @private
374
+ */
375
+ _on_GetEndpointsRequest(message, channel) {
376
+ const request = message.request;
377
+ (0, node_opcua_assert_1.assert)(request.schema.name === "GetEndpointsRequest");
378
+ const response = new node_opcua_service_endpoints_1.GetEndpointsResponse({});
379
+ response.endpoints = this._get_endpoints(null);
380
+ response.endpoints = response.endpoints.filter((endpoint) => !endpoint.restricted);
381
+ // apply filters
382
+ if (request.profileUris && request.profileUris.length > 0) {
383
+ response.endpoints = response.endpoints.filter((endpoint) => {
384
+ return request.profileUris.indexOf(endpoint.transportProfileUri) >= 0;
385
+ });
386
+ }
387
+ // adjust locale on ApplicationName to match requested local or provide
388
+ // a string with neutral locale (locale === null)
389
+ // TODO: find a better way to handle this
390
+ response.endpoints.forEach((endpoint) => {
391
+ endpoint.server.applicationName.locale = "en-US";
392
+ });
393
+ channel.send_response("MSG", response, message, emptyCallback);
394
+ }
395
+ /**
396
+ * @private
397
+ */
398
+ _on_FindServersRequest(message, channel) {
399
+ // Release 1.02 13 OPC Unified Architecture, Part 4 :
400
+ // This Service can be used without security and it is therefore vulnerable to Denial Of Service (DOS)
401
+ // attacks. A Server should minimize the amount of processing required to send the response for this
402
+ // Service. This can be achieved by preparing the result in advance. The Server should also add a
403
+ // short delay before starting processing of a request during high traffic conditions.
404
+ const shortDelay = 100; // milliseconds
405
+ setTimeout(() => {
406
+ const request = message.request;
407
+ (0, node_opcua_assert_1.assert)(request.schema.name === "FindServersRequest");
408
+ if (!(request instanceof node_opcua_service_discovery_1.FindServersRequest)) {
409
+ throw new Error("Invalid request type");
410
+ }
411
+ let servers = this.getServers(channel);
412
+ // apply filters
413
+ // TODO /
414
+ if (request.serverUris && request.serverUris.length > 0) {
415
+ // A serverUri matches the applicationUri from the ApplicationDescription define
416
+ servers = servers.filter((inner_Server) => {
417
+ return request.serverUris.indexOf(inner_Server.applicationUri) >= 0;
418
+ });
419
+ }
420
+ function adapt(applicationDescription) {
421
+ return new node_opcua_service_endpoints_2.ApplicationDescription({
422
+ applicationName: applicationDescription.applicationName,
423
+ applicationType: applicationDescription.applicationType,
424
+ applicationUri: applicationDescription.applicationUri,
425
+ discoveryProfileUri: applicationDescription.discoveryProfileUri,
426
+ discoveryUrls: applicationDescription.discoveryUrls,
427
+ gatewayServerUri: applicationDescription.gatewayServerUri,
428
+ productUri: applicationDescription.productUri
429
+ });
430
+ }
431
+ const response = new node_opcua_service_discovery_1.FindServersResponse({
432
+ servers: servers.map(adapt)
433
+ });
434
+ channel.send_response("MSG", response, message, emptyCallback);
435
+ }, shortDelay);
436
+ }
437
+ /**
438
+ * returns a array of currently active channels
439
+ */
440
+ getChannels() {
441
+ let channels = [];
442
+ for (const endpoint of this.endpoints) {
443
+ const c = endpoint.getChannels();
444
+ channels = channels.concat(c);
445
+ }
446
+ return channels;
447
+ }
448
+ }
449
+ exports.OPCUABaseServer = OPCUABaseServer;
450
+ OPCUABaseServer.makeServiceFault = makeServiceFault;
451
+ /**
452
+ * construct a service Fault response
453
+ * @method makeServiceFault
454
+ * @param statusCode
455
+ * @param messages
456
+ */
457
+ function makeServiceFault(statusCode, messages) {
458
+ const response = new node_opcua_service_secure_channel_1.ServiceFault();
459
+ response.responseHeader.serviceResult = statusCode;
460
+ // xx response.serviceDiagnostics.push( new DiagnosticInfo({ additionalInfo: messages.join("\n")}));
461
+ (0, node_opcua_assert_1.assert)(Array.isArray(messages));
462
+ (0, node_opcua_assert_1.assert)(typeof messages[0] === "string");
463
+ response.responseHeader.stringTable = messages;
464
+ // tslint:disable:no-console
465
+ warningLog(chalk.cyan(" messages "), messages.join("\n"));
466
+ return response;
467
+ }
468
+ // tslint:disable:no-var-requires
469
+ const thenify = require("thenify");
470
+ const opts = { multiArgs: false };
471
+ OPCUABaseServer.prototype.resumeEndPoints = thenify.withCallback(OPCUABaseServer.prototype.resumeEndPoints, opts);
472
+ OPCUABaseServer.prototype.suspendEndPoints = thenify.withCallback(OPCUABaseServer.prototype.suspendEndPoints, opts);
473
+ OPCUABaseServer.prototype.shutdownChannels = thenify.withCallback(OPCUABaseServer.prototype.shutdownChannels, opts);
474
474
  //# sourceMappingURL=base_server.js.map