node-opcua-server 2.166.0 → 2.168.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.
- package/dist/addressSpace_accessor.d.ts +6 -6
- package/dist/addressSpace_accessor.js +2 -2
- package/dist/addressSpace_accessor.js.map +1 -1
- package/dist/base_server.d.ts +14 -3
- package/dist/base_server.js +64 -44
- package/dist/base_server.js.map +1 -1
- package/dist/extract_password_from_blob.js +1 -3
- package/dist/extract_password_from_blob.js.map +1 -1
- package/dist/factory.d.ts +2 -3
- package/dist/factory.js.map +1 -1
- package/dist/filter/check_where_clause_on_address_space.d.ts +2 -2
- package/dist/filter/check_where_clause_on_address_space.js +1 -2
- package/dist/filter/check_where_clause_on_address_space.js.map +1 -1
- package/dist/filter/extract_event_fields.d.ts +3 -3
- package/dist/filter/extract_event_fields.js +1 -2
- package/dist/filter/extract_event_fields.js.map +1 -1
- package/dist/helper.d.ts +3 -3
- package/dist/helper.js +4 -8
- package/dist/helper.js.map +1 -1
- package/dist/i_address_space_accessor.d.ts +4 -4
- package/dist/i_channel_data.d.ts +1 -1
- package/dist/i_register_server_manager.d.ts +1 -1
- package/dist/i_server_side_publish_engine.d.ts +8 -6
- package/dist/i_server_side_publish_engine.js +7 -2
- package/dist/i_server_side_publish_engine.js.map +1 -1
- package/dist/index.d.ts +8 -7
- package/dist/index.js +8 -7
- package/dist/index.js.map +1 -1
- package/dist/invalidate_server_certificate_cache.d.ts +16 -0
- package/dist/invalidate_server_certificate_cache.js +28 -0
- package/dist/invalidate_server_certificate_cache.js.map +1 -0
- package/dist/monitored_item.d.ts +10 -11
- package/dist/monitored_item.js +38 -39
- package/dist/monitored_item.js.map +1 -1
- package/dist/node_sampler.d.ts +1 -1
- package/dist/node_sampler.js +2 -4
- package/dist/node_sampler.js.map +1 -1
- package/dist/opcua_server.d.ts +57 -62
- package/dist/opcua_server.js +10 -10
- package/dist/opcua_server.js.map +1 -1
- package/dist/register_server_manager.d.ts +8 -8
- package/dist/register_server_manager.js +40 -40
- package/dist/register_server_manager.js.map +1 -1
- package/dist/register_server_manager_hidden.d.ts +1 -1
- package/dist/register_server_manager_hidden.js +2 -4
- package/dist/register_server_manager_hidden.js.map +1 -1
- package/dist/register_server_manager_mdns_only.d.ts +1 -1
- package/dist/register_server_manager_mdns_only.js.map +1 -1
- package/dist/sampling_func.d.ts +2 -2
- package/dist/server_capabilities.d.ts +3 -3
- package/dist/server_capabilities.js.map +1 -1
- package/dist/server_end_point.d.ts +47 -4
- package/dist/server_end_point.js +133 -42
- package/dist/server_end_point.js.map +1 -1
- package/dist/server_engine.js +29 -25
- package/dist/server_engine.js.map +1 -1
- package/dist/server_publish_engine.d.ts +5 -5
- package/dist/server_publish_engine.js +29 -23
- package/dist/server_publish_engine.js.map +1 -1
- package/dist/server_publish_engine_for_orphan_subscriptions.d.ts +2 -2
- package/dist/server_publish_engine_for_orphan_subscriptions.js.map +1 -1
- package/dist/server_session.d.ts +9 -10
- package/dist/server_session.js +11 -12
- package/dist/server_session.js.map +1 -1
- package/dist/server_subscription.d.ts +13 -13
- package/dist/server_subscription.js +100 -79
- package/dist/server_subscription.js.map +1 -1
- package/dist/sessions_compatible_for_transfer.d.ts +1 -1
- package/dist/sessions_compatible_for_transfer.js +1 -1
- package/dist/sessions_compatible_for_transfer.js.map +1 -1
- package/dist/user_manager.d.ts +4 -4
- package/dist/user_manager.js +1 -1
- package/dist/user_manager.js.map +1 -1
- package/dist/user_manager_ua.d.ts +2 -2
- package/dist/user_manager_ua.js +2 -2
- package/dist/user_manager_ua.js.map +1 -1
- package/dist/validate_filter.d.ts +7 -4
- package/dist/validate_filter.js +5 -6
- package/dist/validate_filter.js.map +1 -1
- package/package.json +51 -50
- package/source/addressSpace_accessor.ts +24 -24
- package/source/base_server.ts +75 -63
- package/source/extract_password_from_blob.ts +3 -11
- package/source/factory.ts +2 -4
- package/source/filter/check_where_clause_on_address_space.ts +4 -7
- package/source/filter/extract_event_fields.ts +4 -5
- package/source/helper.ts +9 -13
- package/source/i_address_space_accessor.ts +13 -4
- package/source/i_channel_data.ts +1 -1
- package/source/i_register_server_manager.ts +2 -4
- package/source/i_server_side_publish_engine.ts +16 -9
- package/source/index.ts +10 -9
- package/source/invalidate_server_certificate_cache.ts +26 -0
- package/source/monitored_item.ts +44 -42
- package/source/node_sampler.ts +9 -11
- package/source/opcua_server.ts +86 -99
- package/source/register_server_manager.ts +75 -72
- package/source/register_server_manager_hidden.ts +3 -5
- package/source/register_server_manager_mdns_only.ts +1 -3
- package/source/sampling_func.ts +2 -2
- package/source/server_capabilities.ts +9 -6
- package/source/server_end_point.ts +143 -50
- package/source/server_engine.ts +22 -22
- package/source/server_publish_engine.ts +35 -30
- package/source/server_publish_engine_for_orphan_subscriptions.ts +3 -3
- package/source/server_session.ts +36 -33
- package/source/server_subscription.ts +182 -184
- package/source/sessions_compatible_for_transfer.ts +9 -9
- package/source/user_manager.ts +7 -7
- package/source/user_manager_ua.ts +3 -5
- package/source/validate_filter.ts +9 -11
package/source/base_server.ts
CHANGED
|
@@ -4,16 +4,16 @@
|
|
|
4
4
|
// tslint:disable:no-console
|
|
5
5
|
|
|
6
6
|
import fs from "node:fs";
|
|
7
|
+
import { isIP } from "node:net";
|
|
7
8
|
import os from "node:os";
|
|
8
9
|
import path from "node:path";
|
|
9
|
-
import { isIP } from "node:net";
|
|
10
10
|
import { withLock } from "@ster5/global-mutex";
|
|
11
|
-
|
|
11
|
+
|
|
12
12
|
import chalk from "chalk";
|
|
13
13
|
import { assert } from "node-opcua-assert";
|
|
14
14
|
import { getDefaultCertificateManager, makeSubject, type OPCUACertificateManager } from "node-opcua-certificate-manager";
|
|
15
15
|
import { performCertificateSanityCheck } from "node-opcua-client";
|
|
16
|
-
import { type IOPCUASecureObjectOptions, makeApplicationUrn, OPCUASecureObject } from "node-opcua-common";
|
|
16
|
+
import { type IOPCUASecureObjectOptions, invalidateCachedSecrets, makeApplicationUrn, OPCUASecureObject } from "node-opcua-common";
|
|
17
17
|
import { exploreCertificate } from "node-opcua-crypto/web";
|
|
18
18
|
import { coerceLocalizedText } from "node-opcua-data-model";
|
|
19
19
|
import { installPeriodicClockAdjustment, uninstallPeriodicClockAdjustment } from "node-opcua-date-time";
|
|
@@ -26,7 +26,7 @@ import {
|
|
|
26
26
|
ipv4ToHex,
|
|
27
27
|
resolveFullyQualifiedDomainName
|
|
28
28
|
} from "node-opcua-hostname";
|
|
29
|
-
import type { Message, Response, ServerSecureChannelLayer } from "node-opcua-secure-channel";
|
|
29
|
+
import type { Message, Request, Response, ServerSecureChannelLayer } from "node-opcua-secure-channel";
|
|
30
30
|
import { FindServersRequest, FindServersResponse } from "node-opcua-service-discovery";
|
|
31
31
|
import { ApplicationDescription, ApplicationType, GetEndpointsResponse } from "node-opcua-service-endpoints";
|
|
32
32
|
import { ServiceFault } from "node-opcua-service-secure-channel";
|
|
@@ -82,6 +82,11 @@ function cleanupEndpoint(endpoint: OPCUAServerEndPoint) {
|
|
|
82
82
|
endpoint.removeListener("openSecureChannelFailure", endpoint._on_openSecureChannelFailure);
|
|
83
83
|
endpoint._on_openSecureChannelFailure = undefined;
|
|
84
84
|
}
|
|
85
|
+
if (endpoint._on_channel_secured) {
|
|
86
|
+
assert(typeof endpoint._on_channel_secured === "function");
|
|
87
|
+
endpoint.removeListener("channelSecured", endpoint._on_channel_secured);
|
|
88
|
+
endpoint._on_channel_secured = undefined;
|
|
89
|
+
}
|
|
85
90
|
}
|
|
86
91
|
|
|
87
92
|
/**
|
|
@@ -102,7 +107,18 @@ const emptyCallback = () => {
|
|
|
102
107
|
/* empty */
|
|
103
108
|
};
|
|
104
109
|
|
|
105
|
-
export
|
|
110
|
+
export interface OPCUABaseServerEvents {
|
|
111
|
+
request: [request: Request, channel: ServerSecureChannelLayer];
|
|
112
|
+
response: [response: Response, channel: ServerSecureChannelLayer];
|
|
113
|
+
newChannel: [channel: ServerSecureChannelLayer, endpoint: OPCUAServerEndPoint];
|
|
114
|
+
channelSecured: [channel: ServerSecureChannelLayer, endpoint: OPCUAServerEndPoint];
|
|
115
|
+
closeChannel: [channel: ServerSecureChannelLayer, endpoint: OPCUAServerEndPoint];
|
|
116
|
+
connectionRefused: [socketData: ISocketData, endpoint: OPCUAServerEndPoint];
|
|
117
|
+
openSecureChannelFailure: [socketData: ISocketData, channelData: IChannelData, endpoint: OPCUAServerEndPoint];
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
// biome-ignore lint/suspicious/noExplicitAny: must propagate EventEmitter generic
|
|
121
|
+
export class OPCUABaseServer<T extends OPCUABaseServerEvents = any> extends OPCUASecureObject<T> {
|
|
106
122
|
public static makeServiceFault = makeServiceFault;
|
|
107
123
|
|
|
108
124
|
/**
|
|
@@ -208,7 +224,7 @@ export class OPCUABaseServer extends OPCUASecureObject {
|
|
|
208
224
|
return [];
|
|
209
225
|
}
|
|
210
226
|
|
|
211
|
-
|
|
227
|
+
public async createDefaultCertificate(): Promise<void> {
|
|
212
228
|
if (fs.existsSync(this.certificateFile)) {
|
|
213
229
|
return;
|
|
214
230
|
}
|
|
@@ -339,9 +355,7 @@ export class OPCUABaseServer extends OPCUASecureObject {
|
|
|
339
355
|
// recreate with current hostnames
|
|
340
356
|
await this.createDefaultCertificate();
|
|
341
357
|
// invalidate cached cert so next getCertificate() reloads from disk
|
|
342
|
-
|
|
343
|
-
priv.$$certificate = null;
|
|
344
|
-
priv.$$certificateChain = null;
|
|
358
|
+
invalidateCachedSecrets(this);
|
|
345
359
|
}
|
|
346
360
|
|
|
347
361
|
private _checkCertificateSanMismatch(): void {
|
|
@@ -393,11 +407,23 @@ export class OPCUABaseServer extends OPCUASecureObject {
|
|
|
393
407
|
|
|
394
408
|
installPeriodicClockAdjustment();
|
|
395
409
|
// eslint-disable-next-line @typescript-eslint/no-this-alias
|
|
396
|
-
const server = this;
|
|
410
|
+
const server: OPCUABaseServer<OPCUABaseServerEvents> = this;
|
|
397
411
|
const _on_new_channel = function (this: OPCUAServerEndPoint, channel: ServerSecureChannelLayer) {
|
|
398
412
|
server.emit("newChannel", channel, this);
|
|
399
413
|
};
|
|
400
414
|
|
|
415
|
+
const _on_channel_secured = function (this: OPCUAServerEndPoint, channel: ServerSecureChannelLayer) {
|
|
416
|
+
// Install a response interceptor once per channel so the
|
|
417
|
+
// server can emit "response" events for diagnostics.
|
|
418
|
+
// Done here (after OpenSecureChannel) rather than at
|
|
419
|
+
// newChannel time, so the interceptor can rely on
|
|
420
|
+
// securityPolicy/securityMode being populated.
|
|
421
|
+
channel.setResponseInterceptor((_msg, response1) => {
|
|
422
|
+
server.emit("response", response1, channel);
|
|
423
|
+
});
|
|
424
|
+
server.emit("channelSecured", channel, this);
|
|
425
|
+
};
|
|
426
|
+
|
|
401
427
|
const _on_close_channel = function (this: OPCUAServerEndPoint, channel: ServerSecureChannelLayer) {
|
|
402
428
|
server.emit("closeChannel", channel, this);
|
|
403
429
|
};
|
|
@@ -422,6 +448,9 @@ export class OPCUABaseServer extends OPCUASecureObject {
|
|
|
422
448
|
endpoint._on_new_channel = _on_new_channel;
|
|
423
449
|
endpoint.on("newChannel", endpoint._on_new_channel);
|
|
424
450
|
|
|
451
|
+
endpoint._on_channel_secured = _on_channel_secured;
|
|
452
|
+
endpoint.on("channelSecured", endpoint._on_channel_secured);
|
|
453
|
+
|
|
425
454
|
endpoint._on_close_channel = _on_close_channel;
|
|
426
455
|
endpoint.on("closeChannel", endpoint._on_close_channel);
|
|
427
456
|
|
|
@@ -444,17 +473,18 @@ export class OPCUABaseServer extends OPCUASecureObject {
|
|
|
444
473
|
uninstallPeriodicClockAdjustment();
|
|
445
474
|
this.serverCertificateManager.dispose().then(() => {
|
|
446
475
|
debugLog("OPCUABaseServer#shutdown starting");
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
(endpoint: OPCUAServerEndPoint, callback: (err?: Error) => void) => {
|
|
476
|
+
const promises = this.endpoints.map((endpoint) => {
|
|
477
|
+
return new Promise<void>((resolve, reject) => {
|
|
450
478
|
cleanupEndpoint(endpoint);
|
|
451
|
-
endpoint.shutdown(
|
|
452
|
-
}
|
|
453
|
-
|
|
479
|
+
endpoint.shutdown((err) => (err ? reject(err) : resolve()));
|
|
480
|
+
});
|
|
481
|
+
});
|
|
482
|
+
Promise.all(promises)
|
|
483
|
+
.then(() => {
|
|
454
484
|
debugLog("shutdown completed");
|
|
455
|
-
done(
|
|
456
|
-
}
|
|
457
|
-
|
|
485
|
+
done();
|
|
486
|
+
})
|
|
487
|
+
.catch((err) => done(err));
|
|
458
488
|
});
|
|
459
489
|
}
|
|
460
490
|
|
|
@@ -465,28 +495,16 @@ export class OPCUABaseServer extends OPCUASecureObject {
|
|
|
465
495
|
// c8 ignore next
|
|
466
496
|
if (!callback) throw new Error("thenify is not available");
|
|
467
497
|
debugLog("OPCUABaseServer#shutdownChannels");
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
(endpoint: OPCUAServerEndPoint, inner_callback: (err?: Error | null) => void) => {
|
|
498
|
+
const promises = this.endpoints.map((endpoint) => {
|
|
499
|
+
return new Promise<void>((resolve, reject) => {
|
|
471
500
|
debugLog(" shutting down endpoint ", endpoint.endpointDescriptions()[0].endpointUrl);
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
endpoint.shutdown(callback2);
|
|
480
|
-
}
|
|
481
|
-
// xx (callback2: (err?: Error| null) => void) => {
|
|
482
|
-
// xx endpoint.restoreConnection(callback2);
|
|
483
|
-
// xx }
|
|
484
|
-
],
|
|
485
|
-
inner_callback
|
|
486
|
-
);
|
|
487
|
-
},
|
|
488
|
-
callback
|
|
489
|
-
);
|
|
501
|
+
endpoint.abruptlyInterruptChannels();
|
|
502
|
+
endpoint.shutdown((err) => (err ? reject(err) : resolve()));
|
|
503
|
+
});
|
|
504
|
+
});
|
|
505
|
+
Promise.all(promises)
|
|
506
|
+
.then(() => callback())
|
|
507
|
+
.catch((err) => callback?.(err));
|
|
490
508
|
}
|
|
491
509
|
|
|
492
510
|
/**
|
|
@@ -497,13 +515,6 @@ export class OPCUABaseServer extends OPCUASecureObject {
|
|
|
497
515
|
assert(message.requestId !== 0);
|
|
498
516
|
const request = message.request;
|
|
499
517
|
|
|
500
|
-
// install channel._on_response so we can intercept its call and emit the "response" event.
|
|
501
|
-
if (!channel._on_response) {
|
|
502
|
-
channel._on_response = (_msg: string, response1: Response /*, inner_message: Message*/) => {
|
|
503
|
-
this.emit("response", response1, channel);
|
|
504
|
-
};
|
|
505
|
-
}
|
|
506
|
-
|
|
507
518
|
// prepare request
|
|
508
519
|
this.prepare(message, channel);
|
|
509
520
|
|
|
@@ -518,7 +529,7 @@ export class OPCUABaseServer extends OPCUASecureObject {
|
|
|
518
529
|
let errMessage: string;
|
|
519
530
|
let response: Response;
|
|
520
531
|
|
|
521
|
-
this.emit("request", request, channel);
|
|
532
|
+
(this as OPCUABaseServer<OPCUABaseServerEvents>).emit("request", request, channel);
|
|
522
533
|
|
|
523
534
|
try {
|
|
524
535
|
// handler must be named _on_ActionRequest()
|
|
@@ -608,24 +619,24 @@ export class OPCUABaseServer extends OPCUASecureObject {
|
|
|
608
619
|
if (!callback) {
|
|
609
620
|
throw new Error("Internal Error");
|
|
610
621
|
}
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
(ep: OPCUAServerEndPoint, _inner_callback) => {
|
|
622
|
+
const promises = this.endpoints.map((ep) => {
|
|
623
|
+
return new Promise<void>((resolve, reject) => {
|
|
614
624
|
/* c8 ignore next */
|
|
615
625
|
if (doDebug) {
|
|
616
626
|
debugLog("Suspending ", ep.endpointDescriptions()[0].endpointUrl);
|
|
617
627
|
}
|
|
618
|
-
|
|
619
628
|
ep.suspendConnection((err?: Error | null) => {
|
|
620
629
|
/* c8 ignore next */
|
|
621
630
|
if (doDebug) {
|
|
622
631
|
debugLog("Suspended ", ep.endpointDescriptions()[0].endpointUrl);
|
|
623
632
|
}
|
|
624
|
-
|
|
633
|
+
err ? reject(err) : resolve();
|
|
625
634
|
});
|
|
626
|
-
}
|
|
627
|
-
|
|
628
|
-
)
|
|
635
|
+
});
|
|
636
|
+
});
|
|
637
|
+
Promise.all(promises)
|
|
638
|
+
.then(() => callback())
|
|
639
|
+
.catch((err) => callback(err));
|
|
629
640
|
}
|
|
630
641
|
|
|
631
642
|
/**
|
|
@@ -638,13 +649,14 @@ export class OPCUABaseServer extends OPCUASecureObject {
|
|
|
638
649
|
public resumeEndPoints(callback?: (err?: Error | null) => void): void | Promise<void> {
|
|
639
650
|
// c8 ignore next
|
|
640
651
|
if (!callback) throw new Error("thenify is not available");
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
652
|
+
const promises = this.endpoints.map((ep) => {
|
|
653
|
+
return new Promise<void>((resolve, reject) => {
|
|
654
|
+
ep.restoreConnection((err) => (err ? reject(err) : resolve()));
|
|
655
|
+
});
|
|
656
|
+
});
|
|
657
|
+
Promise.all(promises)
|
|
658
|
+
.then(() => callback())
|
|
659
|
+
.catch((err) => callback(err));
|
|
648
660
|
}
|
|
649
661
|
|
|
650
662
|
protected prepare(_message: Message, _channel: ServerSecureChannelLayer): void {
|
|
@@ -28,10 +28,7 @@ export interface ExtractPasswordResult {
|
|
|
28
28
|
* @param serverNonce - the nonce that was sent during
|
|
29
29
|
* CreateSession / last ActivateSession
|
|
30
30
|
*/
|
|
31
|
-
export function extractPasswordFromDecryptedBlob(
|
|
32
|
-
decryptedBuffer: Buffer,
|
|
33
|
-
serverNonce: Nonce
|
|
34
|
-
): ExtractPasswordResult {
|
|
31
|
+
export function extractPasswordFromDecryptedBlob(decryptedBuffer: Buffer, serverNonce: Nonce): ExtractPasswordResult {
|
|
35
32
|
const invalidResult: ExtractPasswordResult = {
|
|
36
33
|
valid: false,
|
|
37
34
|
password: ""
|
|
@@ -56,16 +53,11 @@ export function extractPasswordFromDecryptedBlob(
|
|
|
56
53
|
return invalidResult;
|
|
57
54
|
}
|
|
58
55
|
|
|
59
|
-
const password = decryptedBuffer
|
|
60
|
-
.subarray(4, 4 + passwordLength)
|
|
61
|
-
.toString("utf-8");
|
|
56
|
+
const password = decryptedBuffer.subarray(4, 4 + passwordLength).toString("utf-8");
|
|
62
57
|
|
|
63
58
|
// verify that the trailing bytes match the server nonce
|
|
64
59
|
// (nonce binding — ensures session integrity)
|
|
65
|
-
const trailingNonce = decryptedBuffer.subarray(
|
|
66
|
-
4 + passwordLength,
|
|
67
|
-
4 + passwordLength + serverNonce.length
|
|
68
|
-
);
|
|
60
|
+
const trailingNonce = decryptedBuffer.subarray(4 + passwordLength, 4 + passwordLength + serverNonce.length);
|
|
69
61
|
if (!trailingNonce.equals(serverNonce)) {
|
|
70
62
|
return invalidResult;
|
|
71
63
|
}
|
package/source/factory.ts
CHANGED
|
@@ -5,11 +5,9 @@
|
|
|
5
5
|
import { assert } from "node-opcua-assert";
|
|
6
6
|
import { ExtensionObject } from "node-opcua-extension-object";
|
|
7
7
|
import { getStandardDataTypeFactory } from "node-opcua-factory";
|
|
8
|
-
import { ExpandedNodeId } from "node-opcua-nodeid";
|
|
8
|
+
import type { ExpandedNodeId } from "node-opcua-nodeid";
|
|
9
9
|
|
|
10
|
-
export
|
|
11
|
-
/** */
|
|
12
|
-
}
|
|
10
|
+
export type EngineForFactory = {};
|
|
13
11
|
export class Factory {
|
|
14
12
|
public engine: EngineForFactory;
|
|
15
13
|
|
|
@@ -1,7 +1,6 @@
|
|
|
1
|
-
import { IAddressSpace,
|
|
2
|
-
import { checkFilter } from "node-opcua-service-filter";
|
|
3
|
-
import {
|
|
4
|
-
import { ContentFilter } from "node-opcua-types";
|
|
1
|
+
import type { IAddressSpace, IEventData, ISessionContext } from "node-opcua-address-space-base";
|
|
2
|
+
import { checkFilter, FilterContextOnAddressSpace } from "node-opcua-service-filter";
|
|
3
|
+
import type { ContentFilter } from "node-opcua-types";
|
|
5
4
|
|
|
6
5
|
export function checkWhereClauseOnAdressSpace(
|
|
7
6
|
addressSpace: IAddressSpace,
|
|
@@ -9,8 +8,6 @@ export function checkWhereClauseOnAdressSpace(
|
|
|
9
8
|
whereClause: ContentFilter,
|
|
10
9
|
eventData: IEventData
|
|
11
10
|
): boolean {
|
|
12
|
-
|
|
13
|
-
|
|
14
11
|
// const filterContext: FilterContext = {
|
|
15
12
|
// addressSpace,
|
|
16
13
|
// sessionContext,
|
|
@@ -24,6 +21,6 @@ export function checkWhereClauseOnAdressSpace(
|
|
|
24
21
|
// }
|
|
25
22
|
// };
|
|
26
23
|
const filterContext = new FilterContextOnAddressSpace(sessionContext, eventData);
|
|
27
|
-
|
|
24
|
+
|
|
28
25
|
return checkFilter(filterContext, whereClause);
|
|
29
26
|
}
|
|
@@ -1,8 +1,7 @@
|
|
|
1
|
-
import { IEventData, ISessionContext } from "node-opcua-address-space-base";
|
|
2
|
-
import { extractEventFieldsBase } from "node-opcua-service-filter";
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import { Variant } from "node-opcua-variant";
|
|
1
|
+
import type { IEventData, ISessionContext } from "node-opcua-address-space-base";
|
|
2
|
+
import { extractEventFieldsBase, FilterContextOnAddressSpace } from "node-opcua-service-filter";
|
|
3
|
+
import type { SimpleAttributeOperand } from "node-opcua-types";
|
|
4
|
+
import type { Variant } from "node-opcua-variant";
|
|
6
5
|
//
|
|
7
6
|
|
|
8
7
|
/**
|
package/source/helper.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import 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";
|
|
2
|
+
import type { OPCUAServer } from "./opcua_server";
|
|
3
|
+
import type { ServerEngine } from "./server_engine";
|
|
4
|
+
import type { ServerSession } from "./server_session";
|
|
5
|
+
import { type Subscription, SubscriptionState } from "./server_subscription";
|
|
6
6
|
|
|
7
7
|
const consolelog = (...args: any) => {
|
|
8
8
|
const d = new Date();
|
|
@@ -25,13 +25,9 @@ const info = (subscription: Subscription) => {
|
|
|
25
25
|
SubscriptionState[subscription.state].padEnd(9),
|
|
26
26
|
subscription.state,
|
|
27
27
|
"kac=",
|
|
28
|
-
subscription.currentKeepAliveCount.toString().padStart(3)+
|
|
29
|
-
"/"+
|
|
30
|
-
subscription.maxKeepAliveCount.toString().padStart(3),
|
|
28
|
+
subscription.currentKeepAliveCount.toString().padStart(3) + "/" + subscription.maxKeepAliveCount.toString().padStart(3),
|
|
31
29
|
"ltc=",
|
|
32
|
-
subscription.currentLifetimeCount.toString().padStart(3)+
|
|
33
|
-
"/"+
|
|
34
|
-
subscription.lifeTimeCount.toString().padStart(3),
|
|
30
|
+
subscription.currentLifetimeCount.toString().padStart(3) + "/" + subscription.lifeTimeCount.toString().padStart(3),
|
|
35
31
|
"prc=",
|
|
36
32
|
subscription.publishEngine?.pendingPublishRequestCount.toString().padStart(3),
|
|
37
33
|
"pi=",
|
|
@@ -65,14 +61,14 @@ export function installSubscriptionMonitoring(subscription: Subscription) {
|
|
|
65
61
|
export function installSessionLoggingOnEngine(serverEngine: ServerEngine) {
|
|
66
62
|
function on_create_session(session: ServerSession) {
|
|
67
63
|
try {
|
|
68
|
-
session.on("activate_session",
|
|
64
|
+
session.on("activate_session", () => {
|
|
69
65
|
consolelog("activate_session");
|
|
70
66
|
});
|
|
71
67
|
|
|
72
68
|
session.on("statusChanged", (status) => {
|
|
73
69
|
consolelog("session status changed: ", status);
|
|
74
70
|
});
|
|
75
|
-
session.on("new_subscription",
|
|
71
|
+
session.on("new_subscription", (subscription) => {
|
|
76
72
|
installSubscriptionMonitoring(subscription);
|
|
77
73
|
});
|
|
78
74
|
} catch (err) {
|
|
@@ -80,7 +76,7 @@ export function installSessionLoggingOnEngine(serverEngine: ServerEngine) {
|
|
|
80
76
|
}
|
|
81
77
|
}
|
|
82
78
|
serverEngine.on("create_session", on_create_session);
|
|
83
|
-
serverEngine.once("session_closed",
|
|
79
|
+
serverEngine.once("session_closed", (session) => {
|
|
84
80
|
consolelog("session is closed");
|
|
85
81
|
serverEngine.removeListener("create_session", on_create_session);
|
|
86
82
|
});
|
|
@@ -1,7 +1,16 @@
|
|
|
1
|
-
import { ISessionContext } from "node-opcua-address-space-base";
|
|
2
|
-
import { DataValue } from "node-opcua-data-value";
|
|
3
|
-
import { StatusCode } from "node-opcua-status-code";
|
|
4
|
-
import {
|
|
1
|
+
import type { ISessionContext } from "node-opcua-address-space-base";
|
|
2
|
+
import type { DataValue } from "node-opcua-data-value";
|
|
3
|
+
import type { StatusCode } from "node-opcua-status-code";
|
|
4
|
+
import type {
|
|
5
|
+
BrowseDescriptionOptions,
|
|
6
|
+
BrowseResult,
|
|
7
|
+
CallMethodRequest,
|
|
8
|
+
CallMethodResultOptions,
|
|
9
|
+
HistoryReadRequest,
|
|
10
|
+
HistoryReadResult,
|
|
11
|
+
ReadRequestOptions,
|
|
12
|
+
WriteValue
|
|
13
|
+
} from "node-opcua-types";
|
|
5
14
|
|
|
6
15
|
export interface IAddressSpaceAccessor {
|
|
7
16
|
browse(context: ISessionContext, nodesToBrowse: BrowseDescriptionOptions[]): Promise<BrowseResult[]>;
|
package/source/i_channel_data.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* @module node-opcua-server
|
|
3
3
|
*/
|
|
4
|
-
import { EventEmitter } from "events";
|
|
4
|
+
import type { EventEmitter } from "events";
|
|
5
5
|
|
|
6
6
|
/**
|
|
7
7
|
* Finite State Machine for RegisterServerManager.
|
|
@@ -46,12 +46,10 @@ export enum RegisterServerManagerStatus {
|
|
|
46
46
|
UNREGISTERING = 7,
|
|
47
47
|
UNREGISTERED = 8,
|
|
48
48
|
NOT_APPLICABLE = -1,
|
|
49
|
-
|
|
49
|
+
|
|
50
50
|
DISPOSING = 9
|
|
51
51
|
}
|
|
52
52
|
|
|
53
|
-
|
|
54
|
-
|
|
55
53
|
export interface IRegisterServerManager extends EventEmitter {
|
|
56
54
|
/** The URL of the discovery server the manager is configured to connect to. */
|
|
57
55
|
discoveryServerEndpointUrl: string;
|
|
@@ -1,11 +1,13 @@
|
|
|
1
|
-
import { PublishResponseOptions, PublishResponse, StatusChangeNotification } from "node-opcua-types";
|
|
2
1
|
import assert from "node-opcua-assert";
|
|
3
|
-
import {
|
|
2
|
+
import type { ExtensionObject } from "node-opcua-extension-object";
|
|
3
|
+
import type { SequenceNumberGenerator } from "node-opcua-secure-channel";
|
|
4
|
+
import { PublishResponse, type PublishResponseOptions, type StatusChangeNotification } from "node-opcua-types";
|
|
5
|
+
import type { Subscription } from "./server_subscription";
|
|
4
6
|
|
|
5
7
|
export interface INotifMsg {
|
|
6
8
|
subscriptionId: number;
|
|
7
9
|
sequenceNumber: number;
|
|
8
|
-
notificationData:
|
|
10
|
+
notificationData: (ExtensionObject | null)[] | null;
|
|
9
11
|
moreNotifications: boolean;
|
|
10
12
|
}
|
|
11
13
|
|
|
@@ -25,10 +27,10 @@ export interface IClosedOrTransferredSubscription {
|
|
|
25
27
|
}
|
|
26
28
|
export class TransferredSubscription implements IClosedOrTransferredSubscription {
|
|
27
29
|
public id: number;
|
|
28
|
-
public publishEngine:
|
|
30
|
+
public publishEngine: IServerSidePublishEngine | null;
|
|
29
31
|
public _pending_notification?: StatusChangeNotification;
|
|
30
|
-
private _sequence_number_generator:
|
|
31
|
-
constructor(options: { id: number; generator:
|
|
32
|
+
private _sequence_number_generator: SequenceNumberGenerator | null;
|
|
33
|
+
constructor(options: { id: number; generator: SequenceNumberGenerator; publishEngine: IServerSidePublishEngine }) {
|
|
32
34
|
this.id = options.id;
|
|
33
35
|
this._sequence_number_generator = options.generator;
|
|
34
36
|
this.publishEngine = options.publishEngine;
|
|
@@ -41,8 +43,10 @@ export class TransferredSubscription implements IClosedOrTransferredSubscription
|
|
|
41
43
|
this.publishEngine = null;
|
|
42
44
|
}
|
|
43
45
|
_publish_pending_notifications(): void {
|
|
44
|
-
|
|
45
|
-
|
|
46
|
+
if (!this._pending_notification) {
|
|
47
|
+
throw new Error("Internal Error: no pending notification");
|
|
48
|
+
}
|
|
49
|
+
const notificationMessage = this._pending_notification;
|
|
46
50
|
this._pending_notification = undefined;
|
|
47
51
|
const moreNotifications = false;
|
|
48
52
|
const subscriptionId = this.id;
|
|
@@ -68,7 +72,10 @@ export class TransferredSubscription implements IClosedOrTransferredSubscription
|
|
|
68
72
|
availableSequenceNumbers[availableSequenceNumbers.length - 1] === response.notificationMessage.sequenceNumber
|
|
69
73
|
);
|
|
70
74
|
response.availableSequenceNumbers = availableSequenceNumbers;
|
|
71
|
-
this.publishEngine
|
|
75
|
+
if (!this.publishEngine) {
|
|
76
|
+
throw new Error("Internal Error: publishEngine is null");
|
|
77
|
+
}
|
|
78
|
+
this.publishEngine._send_response(this as unknown as Subscription, response);
|
|
72
79
|
}
|
|
73
80
|
private _get_next_sequence_number(): number {
|
|
74
81
|
return this._sequence_number_generator ? this._sequence_number_generator.next() : 0;
|
package/source/index.ts
CHANGED
|
@@ -9,10 +9,10 @@
|
|
|
9
9
|
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
|
10
10
|
* the Software, and to permit persons to whom the Software is furnished to do so,
|
|
11
11
|
* subject to the following conditions:
|
|
12
|
-
*
|
|
12
|
+
*
|
|
13
13
|
* The above copyright notice and this permission notice shall be included in all
|
|
14
14
|
* copies or substantial portions of the Software.
|
|
15
|
-
*
|
|
15
|
+
*
|
|
16
16
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
17
17
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
|
18
18
|
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
|
@@ -24,15 +24,16 @@
|
|
|
24
24
|
* @module node-opcua-server
|
|
25
25
|
*/
|
|
26
26
|
export * from "./base_server";
|
|
27
|
-
export * from "./
|
|
27
|
+
export * from "./helper";
|
|
28
|
+
export * from "./invalidate_server_certificate_cache";
|
|
29
|
+
export * from "./monitored_item";
|
|
30
|
+
export * from "./opcua_server";
|
|
28
31
|
export * from "./register_server_manager";
|
|
29
32
|
export * from "./register_server_manager_mdns_only";
|
|
30
|
-
export * from "./server_publish_engine";
|
|
31
|
-
export * from "./server_subscription";
|
|
32
|
-
export * from "./server_session";
|
|
33
33
|
export * from "./server_capabilities";
|
|
34
|
+
export * from "./server_end_point";
|
|
34
35
|
export * from "./server_engine";
|
|
35
|
-
export * from "./
|
|
36
|
-
export * from "./
|
|
36
|
+
export * from "./server_publish_engine";
|
|
37
|
+
export * from "./server_session";
|
|
38
|
+
export * from "./server_subscription";
|
|
37
39
|
export * from "./user_manager";
|
|
38
|
-
export * from "./helper";
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module node-opcua-server
|
|
3
|
+
*/
|
|
4
|
+
import { invalidateCachedSecrets } from "node-opcua-common";
|
|
5
|
+
import type { OPCUABaseServer } from "./base_server";
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Invalidate all cached certificates on a running server so that
|
|
9
|
+
* subsequent GetEndpoints / OpenSecureChannel calls reflect the
|
|
10
|
+
* current on-disk certificate.
|
|
11
|
+
*
|
|
12
|
+
* Call this after replacing the server's certificate PEM file.
|
|
13
|
+
* Works with or without push certificate management.
|
|
14
|
+
*
|
|
15
|
+
* ```ts
|
|
16
|
+
* // 1. write new cert to disk (e.g. via CertificateManager)
|
|
17
|
+
* // 2. tell the server to pick it up:
|
|
18
|
+
* invalidateServerCertificateCache(server);
|
|
19
|
+
* ```
|
|
20
|
+
*/
|
|
21
|
+
export function invalidateServerCertificateCache(server: OPCUABaseServer): void {
|
|
22
|
+
invalidateCachedSecrets(server);
|
|
23
|
+
for (const ep of server.endpoints) {
|
|
24
|
+
ep.invalidateCertificates();
|
|
25
|
+
}
|
|
26
|
+
}
|