node-opcua-server 2.165.2 → 2.167.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/base_server.js +1 -3
- package/dist/base_server.js.map +1 -1
- package/dist/extract_password_from_blob.d.ts +29 -0
- package/dist/extract_password_from_blob.js +55 -0
- package/dist/extract_password_from_blob.js.map +1 -0
- package/dist/opcua_server.js +6 -6
- 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/server_end_point.d.ts +2 -2
- package/dist/server_end_point.js +5 -12
- package/dist/server_end_point.js.map +1 -1
- package/package.json +42 -41
- package/source/base_server.ts +2 -4
- package/source/extract_password_from_blob.ts +74 -0
- package/source/opcua_server.ts +21 -15
- package/source/register_server_manager.ts +75 -72
- package/source/server_end_point.ts +16 -23
|
@@ -1,38 +1,36 @@
|
|
|
1
|
-
|
|
1
|
+
/**
|
|
2
2
|
* @module node-opcua-server
|
|
3
3
|
*/
|
|
4
4
|
// tslint:disable:no-console
|
|
5
|
-
import { EventEmitter } from "events";
|
|
5
|
+
import { EventEmitter } from "node:events";
|
|
6
6
|
import chalk from "chalk";
|
|
7
7
|
|
|
8
8
|
import { assert } from "node-opcua-assert";
|
|
9
|
-
import { UAString } from "node-opcua-basic-types";
|
|
10
|
-
import {
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
OPCUAClientBaseOptions,
|
|
15
|
-
ResponseCallback
|
|
16
|
-
} from "node-opcua-client";
|
|
17
|
-
import { make_debugLog, checkDebugFlag, make_warningLog } from "node-opcua-debug";
|
|
9
|
+
import type { UAString } from "node-opcua-basic-types";
|
|
10
|
+
import type { OPCUACertificateManager } from "node-opcua-certificate-manager";
|
|
11
|
+
import { coerceLocalizedText, type LocalizedTextOptions, OPCUAClientBase, type ResponseCallback } from "node-opcua-client";
|
|
12
|
+
import { exploreCertificate } from "node-opcua-crypto/web";
|
|
13
|
+
import { checkDebugFlag, make_debugLog, make_warningLog } from "node-opcua-debug";
|
|
18
14
|
import { resolveFullyQualifiedDomainName } from "node-opcua-hostname";
|
|
19
15
|
import { coerceSecurityPolicy, MessageSecurityMode, SecurityPolicy } from "node-opcua-secure-channel";
|
|
20
16
|
import {
|
|
21
17
|
RegisterServer2Request,
|
|
22
|
-
RegisterServer2Response,
|
|
18
|
+
type RegisterServer2Response,
|
|
23
19
|
RegisterServerRequest,
|
|
24
|
-
RegisterServerResponse
|
|
20
|
+
type RegisterServerResponse
|
|
25
21
|
} from "node-opcua-service-discovery";
|
|
26
|
-
import {
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
22
|
+
import {
|
|
23
|
+
type ApplicationType,
|
|
24
|
+
type EndpointDescription,
|
|
25
|
+
MdnsDiscoveryConfiguration,
|
|
26
|
+
type RegisteredServerOptions
|
|
27
|
+
} from "node-opcua-types";
|
|
28
|
+
import { type IRegisterServerManager, RegisterServerManagerStatus } from "./i_register_server_manager";
|
|
29
|
+
|
|
30
|
+
const _doDebug = checkDebugFlag("REGISTER_LDS");
|
|
32
31
|
const debugLog = make_debugLog("REGISTER_LDS");
|
|
33
32
|
const warningLog = make_warningLog("REGISTER_LDS");
|
|
34
33
|
|
|
35
|
-
|
|
36
34
|
const g_DefaultRegistrationServerTimeout = 8 * 60 * 1000; // 8 minutes
|
|
37
35
|
|
|
38
36
|
function securityPolicyLevel(securityPolicy: UAString): number {
|
|
@@ -110,7 +108,7 @@ function constructRegisteredServer(server: IPartialServer, isOnline: boolean): R
|
|
|
110
108
|
assert(!isOnline || discoveryUrls.length >= 1, "expecting some discoveryUrls if we go online .... ");
|
|
111
109
|
|
|
112
110
|
const info = exploreCertificate(server.getCertificate());
|
|
113
|
-
const
|
|
111
|
+
const _commonName = info.tbsCertificate.subject.commonName ?? "";
|
|
114
112
|
|
|
115
113
|
const serverUri = info.tbsCertificate.extensions?.subjectAltName?.uniformResourceIdentifier[0];
|
|
116
114
|
// c8 ignore next
|
|
@@ -122,7 +120,7 @@ function constructRegisteredServer(server: IPartialServer, isOnline: boolean): R
|
|
|
122
120
|
"\n subjectAltName : ",
|
|
123
121
|
info.tbsCertificate.extensions?.subjectAltName,
|
|
124
122
|
"\n commonName : ",
|
|
125
|
-
info.tbsCertificate.subject.commonName
|
|
123
|
+
info.tbsCertificate.subject.commonName,
|
|
126
124
|
"\n serverInfo.applicationUri : ",
|
|
127
125
|
server.serverInfo.applicationUri
|
|
128
126
|
);
|
|
@@ -203,7 +201,7 @@ async function sendRegisterServerRequest(server: IPartialServer, client: ClientB
|
|
|
203
201
|
const request = constructRegisterServer2Request(server, isOnline);
|
|
204
202
|
|
|
205
203
|
await new Promise<void>((resolve, reject) => {
|
|
206
|
-
client.performMessageTransaction(request, (err: Error | null,
|
|
204
|
+
client.performMessageTransaction(request, (err: Error | null, _response?: RegisterServer2Response) => {
|
|
207
205
|
if (!err) {
|
|
208
206
|
// RegisterServerResponse
|
|
209
207
|
debugLog("RegisterServerManager#_registerServer sendRegisterServer2Request has succeeded (isOnline", isOnline, ")");
|
|
@@ -213,7 +211,7 @@ async function sendRegisterServerRequest(server: IPartialServer, client: ClientB
|
|
|
213
211
|
debugLog("RegisterServerManager#_registerServer" + " falling back to using sendRegisterServerRequest instead");
|
|
214
212
|
// fall back to
|
|
215
213
|
const request1 = constructRegisterServerRequest(server, isOnline);
|
|
216
|
-
client.performMessageTransaction(request1, (err1: Error | null,
|
|
214
|
+
client.performMessageTransaction(request1, (err1: Error | null, _response1?: RegisterServerResponse) => {
|
|
217
215
|
if (!err1) {
|
|
218
216
|
debugLog(
|
|
219
217
|
"RegisterServerManager#_registerServer sendRegisterServerRequest " + "has succeeded (isOnline",
|
|
@@ -227,10 +225,9 @@ async function sendRegisterServerRequest(server: IPartialServer, client: ClientB
|
|
|
227
225
|
isOnline,
|
|
228
226
|
")"
|
|
229
227
|
);
|
|
230
|
-
reject(err1
|
|
228
|
+
reject(err1);
|
|
231
229
|
});
|
|
232
230
|
});
|
|
233
|
-
|
|
234
231
|
});
|
|
235
232
|
}
|
|
236
233
|
|
|
@@ -256,7 +253,7 @@ export interface RegisterServerManagerOptions {
|
|
|
256
253
|
let g_registeringClientCounter = 0;
|
|
257
254
|
/**
|
|
258
255
|
* RegisterServerManager is responsible to Register an opcua server on a LDS or LDS-ME server
|
|
259
|
-
* This class takes in charge :
|
|
256
|
+
* This class takes in charge :
|
|
260
257
|
* - the initial registration of a server
|
|
261
258
|
* - the regular registration renewal (every 8 minutes or so ...)
|
|
262
259
|
* - dealing with cases where LDS is not up and running when server starts.
|
|
@@ -349,7 +346,7 @@ export class RegisterServerManager extends EventEmitter implements IRegisterServ
|
|
|
349
346
|
public async start(): Promise<void> {
|
|
350
347
|
debugLog("RegisterServerManager#start");
|
|
351
348
|
if (this.state !== RegisterServerManagerStatus.INACTIVE) {
|
|
352
|
-
throw new Error(
|
|
349
|
+
throw new Error(`RegisterServer process already started: ${RegisterServerManagerStatus[this.state]}`);
|
|
353
350
|
}
|
|
354
351
|
this.discoveryServerEndpointUrl = resolveFullyQualifiedDomainName(this.discoveryServerEndpointUrl);
|
|
355
352
|
|
|
@@ -359,7 +356,7 @@ export class RegisterServerManager extends EventEmitter implements IRegisterServ
|
|
|
359
356
|
// This method is called without await to ensure it is non-blocking.
|
|
360
357
|
// The catch block handles any synchronous errors.
|
|
361
358
|
this.#_runRegistrationProcess().catch((err) => {
|
|
362
|
-
warningLog("Synchronous error in #_runRegistrationProcess: ",
|
|
359
|
+
warningLog("Synchronous error in #_runRegistrationProcess: ", err?.message);
|
|
363
360
|
});
|
|
364
361
|
}
|
|
365
362
|
|
|
@@ -370,7 +367,12 @@ export class RegisterServerManager extends EventEmitter implements IRegisterServ
|
|
|
370
367
|
*/
|
|
371
368
|
async #_runRegistrationProcess(): Promise<void> {
|
|
372
369
|
while (this.getState() !== RegisterServerManagerStatus.WAITING && !this.#_isTerminating()) {
|
|
373
|
-
debugLog(
|
|
370
|
+
debugLog(
|
|
371
|
+
"RegisterServerManager#_runRegistrationProcess - state =",
|
|
372
|
+
RegisterServerManagerStatus[this.state],
|
|
373
|
+
"isTerminating =",
|
|
374
|
+
this.#_isTerminating()
|
|
375
|
+
);
|
|
374
376
|
try {
|
|
375
377
|
if (this.getState() === RegisterServerManagerStatus.INACTIVE) {
|
|
376
378
|
this.#_setState(RegisterServerManagerStatus.INITIALIZING);
|
|
@@ -399,7 +401,7 @@ export class RegisterServerManager extends EventEmitter implements IRegisterServ
|
|
|
399
401
|
this.#_trigger_next();
|
|
400
402
|
return;
|
|
401
403
|
} catch (err) {
|
|
402
|
-
debugLog("RegisterServerManager#_runRegistrationProcess - operation failed!", (
|
|
404
|
+
debugLog("RegisterServerManager#_runRegistrationProcess - operation failed!", (err as Error).message);
|
|
403
405
|
if (!this.#_isTerminating()) {
|
|
404
406
|
this.#_setState(RegisterServerManagerStatus.INACTIVE);
|
|
405
407
|
this.#_emitEvent("serverRegistrationFailure");
|
|
@@ -413,7 +415,10 @@ export class RegisterServerManager extends EventEmitter implements IRegisterServ
|
|
|
413
415
|
}
|
|
414
416
|
}
|
|
415
417
|
#_isTerminating(): boolean {
|
|
416
|
-
return
|
|
418
|
+
return (
|
|
419
|
+
this.getState() === RegisterServerManagerStatus.UNREGISTERING ||
|
|
420
|
+
this.getState() === RegisterServerManagerStatus.DISPOSING
|
|
421
|
+
);
|
|
417
422
|
}
|
|
418
423
|
|
|
419
424
|
/**
|
|
@@ -435,30 +440,28 @@ export class RegisterServerManager extends EventEmitter implements IRegisterServ
|
|
|
435
440
|
assert(typeof this.discoveryServerEndpointUrl === "string");
|
|
436
441
|
assert(this.state === RegisterServerManagerStatus.INITIALIZING);
|
|
437
442
|
|
|
438
|
-
|
|
439
443
|
this.selectedEndpoint = undefined;
|
|
440
444
|
|
|
441
|
-
const applicationName = coerceLocalizedText(this.server.serverInfo.applicationName
|
|
445
|
+
const applicationName = coerceLocalizedText(this.server.serverInfo.applicationName)?.text || undefined;
|
|
442
446
|
this.server.serverCertificateManager.referenceCounter++;
|
|
443
447
|
|
|
444
448
|
const server = this.server;
|
|
445
449
|
const prefix = `Client-${g_registeringClientCounter++}`;
|
|
446
450
|
const action = "initializing";
|
|
447
451
|
const ldsInfo = this.discoveryServerEndpointUrl;
|
|
448
|
-
const
|
|
449
|
-
const clientName = `${prefix} for server ${
|
|
452
|
+
const serverAppUri = this.server?.serverInfo.applicationUri ?? "";
|
|
453
|
+
const clientName = `${prefix} for server ${serverAppUri} to LDS ${ldsInfo} for ${action}`;
|
|
450
454
|
|
|
451
455
|
const registrationClient = OPCUAClientBase.create({
|
|
452
456
|
clientName,
|
|
453
457
|
applicationName,
|
|
454
|
-
applicationUri: server.serverInfo.applicationUri
|
|
458
|
+
applicationUri: server.serverInfo.applicationUri ?? "",
|
|
455
459
|
connectionStrategy: infinite_connectivity_strategy,
|
|
456
460
|
clientCertificateManager: server.serverCertificateManager,
|
|
457
461
|
certificateFile: server.certificateFile,
|
|
458
462
|
privateKeyFile: server.privateKeyFile
|
|
459
463
|
}) as ClientBaseEx;
|
|
460
464
|
|
|
461
|
-
|
|
462
465
|
registrationClient.on("backoff", (nbRetry: number, delay: number) => {
|
|
463
466
|
if (this.state !== RegisterServerManagerStatus.INITIALIZING) return; // Ignore event if state has changed
|
|
464
467
|
debugLog("RegisterServerManager - received backoff");
|
|
@@ -489,24 +492,18 @@ export class RegisterServerManager extends EventEmitter implements IRegisterServ
|
|
|
489
492
|
return;
|
|
490
493
|
}
|
|
491
494
|
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
+
const endpoints = await registrationClient.getEndpoints();
|
|
496
|
+
if (!endpoints || endpoints.length === 0) {
|
|
497
|
+
throw new Error("Cannot retrieve endpoints from discovery server");
|
|
498
|
+
}
|
|
499
|
+
const endpoint = findSecureEndpoint(endpoints);
|
|
495
500
|
if (!endpoint) {
|
|
496
501
|
throw new Error("Cannot find Secure endpoint");
|
|
497
502
|
}
|
|
498
503
|
|
|
499
|
-
|
|
500
|
-
assert(endpoint.serverCertificate);
|
|
501
|
-
this.selectedEndpoint = endpoint;
|
|
502
|
-
} else {
|
|
503
|
-
this.selectedEndpoint = undefined;
|
|
504
|
-
}
|
|
504
|
+
this.selectedEndpoint = endpoint.serverCertificate ? endpoint : undefined;
|
|
505
505
|
|
|
506
506
|
this._serverEndpoints = registrationClient._serverEndpoints;
|
|
507
|
-
} catch (err) {
|
|
508
|
-
// Do not set state to INACTIVE or rethrow here, let the caller handle it.
|
|
509
|
-
throw err;
|
|
510
507
|
} finally {
|
|
511
508
|
if (this._registration_client) {
|
|
512
509
|
const tmp = this._registration_client;
|
|
@@ -557,7 +554,7 @@ export class RegisterServerManager extends EventEmitter implements IRegisterServ
|
|
|
557
554
|
this.#_setState(RegisterServerManagerStatus.REGISTERING);
|
|
558
555
|
this.#_emitEvent("serverRegistrationPending");
|
|
559
556
|
|
|
560
|
-
this.#_registerOrUnregisterServer(/*isOnline=*/true)
|
|
557
|
+
this.#_registerOrUnregisterServer(/*isOnline=*/ true)
|
|
561
558
|
.then(() => after_register())
|
|
562
559
|
.catch((err) => after_register(err));
|
|
563
560
|
}, this.timeout);
|
|
@@ -577,7 +574,6 @@ export class RegisterServerManager extends EventEmitter implements IRegisterServ
|
|
|
577
574
|
this._registrationTimerId = null;
|
|
578
575
|
}
|
|
579
576
|
|
|
580
|
-
|
|
581
577
|
// Immediately set state to signal a stop
|
|
582
578
|
this.#_setState(RegisterServerManagerStatus.UNREGISTERING);
|
|
583
579
|
|
|
@@ -586,7 +582,7 @@ export class RegisterServerManager extends EventEmitter implements IRegisterServ
|
|
|
586
582
|
|
|
587
583
|
if (this.selectedEndpoint) {
|
|
588
584
|
try {
|
|
589
|
-
await this.#_registerOrUnregisterServer(/* isOnline= */false);
|
|
585
|
+
await this.#_registerOrUnregisterServer(/* isOnline= */ false);
|
|
590
586
|
this.#_setState(RegisterServerManagerStatus.UNREGISTERED);
|
|
591
587
|
this.#_emitEvent("serverUnregistered");
|
|
592
588
|
} catch (err) {
|
|
@@ -615,9 +611,12 @@ export class RegisterServerManager extends EventEmitter implements IRegisterServ
|
|
|
615
611
|
debugLog("RegisterServerManager#_registerServer isOnline:", isOnline);
|
|
616
612
|
|
|
617
613
|
assert(this.selectedEndpoint, "must have a selected endpoint");
|
|
618
|
-
assert(this.server
|
|
614
|
+
assert(this.server?.serverType !== undefined, " must have a valid server Type");
|
|
619
615
|
|
|
620
|
-
|
|
616
|
+
if (!this.server) {
|
|
617
|
+
throw new Error("RegisterServerManager: server is not set");
|
|
618
|
+
}
|
|
619
|
+
const server = this.server;
|
|
621
620
|
const selectedEndpoint = this.selectedEndpoint;
|
|
622
621
|
if (!selectedEndpoint) {
|
|
623
622
|
warningLog("Warning: cannot register server - no endpoint available");
|
|
@@ -626,18 +625,18 @@ export class RegisterServerManager extends EventEmitter implements IRegisterServ
|
|
|
626
625
|
}
|
|
627
626
|
|
|
628
627
|
server.serverCertificateManager.referenceCounter++;
|
|
629
|
-
const applicationName: string | undefined = coerceLocalizedText(server.serverInfo.applicationName
|
|
628
|
+
const applicationName: string | undefined = coerceLocalizedText(server.serverInfo.applicationName)?.text || undefined;
|
|
630
629
|
|
|
631
630
|
const prefix = `Client-${g_registeringClientCounter++}`;
|
|
632
631
|
const action = isOnline ? "registering" : "unregistering";
|
|
633
632
|
const ldsInfo = this.discoveryServerEndpointUrl;
|
|
634
|
-
const
|
|
635
|
-
const clientName = `${prefix} for server ${
|
|
633
|
+
const serverAppUri = server.serverInfo.applicationUri ?? "";
|
|
634
|
+
const clientName = `${prefix} for server ${serverAppUri} to LDS ${ldsInfo} for ${action}`;
|
|
636
635
|
|
|
637
636
|
const client = OPCUAClientBase.create({
|
|
638
637
|
clientName,
|
|
639
638
|
applicationName,
|
|
640
|
-
applicationUri: server.serverInfo.applicationUri
|
|
639
|
+
applicationUri: server.serverInfo.applicationUri ?? "",
|
|
641
640
|
connectionStrategy: no_retry_connectivity_strategy,
|
|
642
641
|
clientCertificateManager: server.serverCertificateManager,
|
|
643
642
|
|
|
@@ -645,8 +644,7 @@ export class RegisterServerManager extends EventEmitter implements IRegisterServ
|
|
|
645
644
|
securityPolicy: coerceSecurityPolicy(selectedEndpoint.securityPolicyUri),
|
|
646
645
|
serverCertificate: selectedEndpoint.serverCertificate,
|
|
647
646
|
certificateFile: server.certificateFile,
|
|
648
|
-
privateKeyFile: server.privateKeyFile
|
|
649
|
-
|
|
647
|
+
privateKeyFile: server.privateKeyFile
|
|
650
648
|
}) as ClientBaseEx;
|
|
651
649
|
client.on("backoff", (nbRetry, delay) => {
|
|
652
650
|
debugLog(client.clientCertificateManager, "backoff trying to connect to the LDS has failed", nbRetry, delay);
|
|
@@ -654,30 +652,36 @@ export class RegisterServerManager extends EventEmitter implements IRegisterServ
|
|
|
654
652
|
|
|
655
653
|
this._registration_client = client;
|
|
656
654
|
|
|
657
|
-
|
|
655
|
+
const endpointUrl = selectedEndpoint.endpointUrl;
|
|
656
|
+
if (!endpointUrl) {
|
|
657
|
+
throw new Error("selectedEndpoint.endpointUrl is missing — cannot connect to LDS");
|
|
658
|
+
}
|
|
659
|
+
debugLog("lds endpoint uri : ", endpointUrl);
|
|
658
660
|
|
|
659
|
-
const state = isOnline ? "
|
|
661
|
+
const state = isOnline ? "RegisterServer" : "UnRegisterServer";
|
|
660
662
|
try {
|
|
661
|
-
await client.connect(
|
|
663
|
+
await client.connect(endpointUrl);
|
|
662
664
|
|
|
663
665
|
// Check state again after connection is established
|
|
664
666
|
if (this.getState() === expectedState) {
|
|
665
667
|
try {
|
|
666
|
-
await sendRegisterServerRequest(server, client as ClientBaseEx, isOnline)
|
|
668
|
+
await sendRegisterServerRequest(server, client as ClientBaseEx, isOnline);
|
|
667
669
|
} catch (err) {
|
|
668
670
|
if (this.getState() !== expectedState) {
|
|
669
|
-
warningLog(
|
|
670
|
-
|
|
671
|
+
warningLog(
|
|
672
|
+
`${state} '${this.server?.serverInfo.applicationUri}' to the LDS has failed during secure connection to the LDS server`
|
|
673
|
+
);
|
|
674
|
+
warningLog(chalk.red(" Error message:"), (err as Error).message); // Do not rethrow here, let the caller
|
|
671
675
|
}
|
|
672
676
|
}
|
|
673
677
|
} else {
|
|
674
678
|
debugLog("RegisterServerManager#_registerServer: aborted ");
|
|
675
679
|
}
|
|
676
|
-
|
|
677
680
|
} catch (err) {
|
|
678
681
|
if (this.getState() !== expectedState) {
|
|
679
|
-
|
|
680
|
-
|
|
682
|
+
warningLog(
|
|
683
|
+
`${state} '${this.server?.serverInfo.applicationUri}' cannot connect to LDS at endpoint ${client.clientName}, ${selectedEndpoint.endpointUrl} :`
|
|
684
|
+
);
|
|
681
685
|
warningLog(chalk.red(" Error message:"), (err as Error).message);
|
|
682
686
|
}
|
|
683
687
|
} finally {
|
|
@@ -700,8 +704,7 @@ export class RegisterServerManager extends EventEmitter implements IRegisterServ
|
|
|
700
704
|
if (this._registration_client) {
|
|
701
705
|
const client = this._registration_client;
|
|
702
706
|
this._registration_client = null;
|
|
703
|
-
debugLog("RegisterServerManager#_cancel_pending_client_if_any "
|
|
704
|
-
+ "=> wee need to disconnect_registration_client");
|
|
707
|
+
debugLog("RegisterServerManager#_cancel_pending_client_if_any " + "=> wee need to disconnect_registration_client");
|
|
705
708
|
try {
|
|
706
709
|
await client.disconnect();
|
|
707
710
|
} catch (err) {
|
|
@@ -10,7 +10,7 @@ import chalk from "chalk";
|
|
|
10
10
|
|
|
11
11
|
import { assert } from "node-opcua-assert";
|
|
12
12
|
import type { OPCUACertificateManager } from "node-opcua-certificate-manager";
|
|
13
|
-
import { type Certificate, makeSHA1Thumbprint, type PrivateKey, split_der } from "node-opcua-crypto/web";
|
|
13
|
+
import { type Certificate, combine_der, makeSHA1Thumbprint, type PrivateKey, split_der } from "node-opcua-crypto/web";
|
|
14
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 {
|
|
@@ -69,9 +69,8 @@ function extractChannelData(channel: ServerSecureChannelLayer): IChannelData {
|
|
|
69
69
|
|
|
70
70
|
function dumpChannelInfo(channels: ServerSecureChannelLayer[]): void {
|
|
71
71
|
function d(s: IServerSessionBase) {
|
|
72
|
-
return `[ status=${s.status} lastSeen=${s.clientLastContactTime.toFixed(0)}ms sessionName=${s.sessionName} timeout=${
|
|
73
|
-
|
|
74
|
-
} ]`;
|
|
72
|
+
return `[ status=${s.status} lastSeen=${s.clientLastContactTime.toFixed(0)}ms sessionName=${s.sessionName} timeout=${s.sessionTimeout
|
|
73
|
+
} ]`;
|
|
75
74
|
}
|
|
76
75
|
function dumpChannel(channel: ServerSecureChannelLayer): void {
|
|
77
76
|
console.log("------------------------------------------------------");
|
|
@@ -98,7 +97,8 @@ function dumpChannelInfo(channels: ServerSecureChannelLayer[]): void {
|
|
|
98
97
|
console.log("------------------------------------------------------");
|
|
99
98
|
}
|
|
100
99
|
|
|
101
|
-
const
|
|
100
|
+
const emptyCertificateChain: Certificate[] = [];
|
|
101
|
+
|
|
102
102
|
// biome-ignore lint/suspicious/noExplicitAny: deliberate null→PrivateKey sentinel
|
|
103
103
|
const emptyPrivateKey = null as any as PrivateKey;
|
|
104
104
|
|
|
@@ -116,7 +116,7 @@ export interface OPCUAServerEndPointOptions {
|
|
|
116
116
|
/**
|
|
117
117
|
* the DER certificate chain
|
|
118
118
|
*/
|
|
119
|
-
certificateChain: Certificate;
|
|
119
|
+
certificateChain: Certificate[];
|
|
120
120
|
|
|
121
121
|
/**
|
|
122
122
|
* privateKey
|
|
@@ -333,7 +333,7 @@ export class OPCUAServerEndPoint extends EventEmitter implements ServerSecureCha
|
|
|
333
333
|
public _on_connectionRefused?: (socketData: ISocketData) => void;
|
|
334
334
|
public _on_openSecureChannelFailure?: (socketData: ISocketData, channelData: IChannelData) => void;
|
|
335
335
|
|
|
336
|
-
private _certificateChain: Certificate;
|
|
336
|
+
private _certificateChain: Certificate[];
|
|
337
337
|
private _privateKey: PrivateKey;
|
|
338
338
|
private _channels: { [key: string]: ServerSecureChannelLayer };
|
|
339
339
|
private _server?: Server;
|
|
@@ -390,7 +390,7 @@ export class OPCUAServerEndPoint extends EventEmitter implements ServerSecureCha
|
|
|
390
390
|
}
|
|
391
391
|
|
|
392
392
|
public dispose(): void {
|
|
393
|
-
this._certificateChain =
|
|
393
|
+
this._certificateChain = emptyCertificateChain;
|
|
394
394
|
this._privateKey = emptyPrivateKey;
|
|
395
395
|
|
|
396
396
|
assert(Object.keys(this._channels).length === 0, "OPCUAServerEndPoint channels must have been deleted");
|
|
@@ -417,7 +417,7 @@ export class OPCUAServerEndPoint extends EventEmitter implements ServerSecureCha
|
|
|
417
417
|
" l = " +
|
|
418
418
|
this._endpoints.length +
|
|
419
419
|
" " +
|
|
420
|
-
makeSHA1Thumbprint(this.
|
|
420
|
+
makeSHA1Thumbprint(this.getCertificate()).toString("hex");
|
|
421
421
|
return txt;
|
|
422
422
|
}
|
|
423
423
|
|
|
@@ -429,13 +429,13 @@ export class OPCUAServerEndPoint extends EventEmitter implements ServerSecureCha
|
|
|
429
429
|
* Returns the X509 DER form of the server certificate
|
|
430
430
|
*/
|
|
431
431
|
public getCertificate(): Certificate {
|
|
432
|
-
return
|
|
432
|
+
return this.getCertificateChain()[0];
|
|
433
433
|
}
|
|
434
434
|
|
|
435
435
|
/**
|
|
436
436
|
* Returns the X509 DER form of the server certificate
|
|
437
437
|
*/
|
|
438
|
-
public getCertificateChain(): Certificate {
|
|
438
|
+
public getCertificateChain(): Certificate[] {
|
|
439
439
|
return this._certificateChain;
|
|
440
440
|
}
|
|
441
441
|
|
|
@@ -687,7 +687,7 @@ export class OPCUAServerEndPoint extends EventEmitter implements ServerSecureCha
|
|
|
687
687
|
|
|
688
688
|
this._server.listen(
|
|
689
689
|
listenOptions,
|
|
690
|
-
/*"::",*/
|
|
690
|
+
/*"::",*/(err?: Error) => {
|
|
691
691
|
// 'listening' listener
|
|
692
692
|
debugLog(chalk.green.bold("LISTENING TO PORT "), this.port, "err ", err);
|
|
693
693
|
assert(!err, " cannot listen to port ");
|
|
@@ -877,7 +877,7 @@ export class OPCUAServerEndPoint extends EventEmitter implements ServerSecureCha
|
|
|
877
877
|
debugLog(
|
|
878
878
|
chalk.bgWhite.cyan(
|
|
879
879
|
"OPCUAServerEndPoint#_on_client_connection " +
|
|
880
|
-
|
|
880
|
+
"SERVER END POINT IS PROBABLY SHUTTING DOWN !!! - Connection is refused"
|
|
881
881
|
)
|
|
882
882
|
);
|
|
883
883
|
socket.end();
|
|
@@ -887,7 +887,7 @@ export class OPCUAServerEndPoint extends EventEmitter implements ServerSecureCha
|
|
|
887
887
|
console.log(
|
|
888
888
|
chalk.bgWhite.cyan(
|
|
889
889
|
"OPCUAServerEndPoint#_on_client_connection " +
|
|
890
|
-
|
|
890
|
+
"The maximum number of connection has been reached - Connection is refused"
|
|
891
891
|
)
|
|
892
892
|
);
|
|
893
893
|
const reason = `maxConnections reached (${this.maxConnections})`;
|
|
@@ -1130,7 +1130,7 @@ interface MakeEndpointDescriptionOptions {
|
|
|
1130
1130
|
*/
|
|
1131
1131
|
hostname: string;
|
|
1132
1132
|
|
|
1133
|
-
serverCertificateChain: Certificate;
|
|
1133
|
+
serverCertificateChain: Certificate[];
|
|
1134
1134
|
/**
|
|
1135
1135
|
*
|
|
1136
1136
|
*/
|
|
@@ -1224,13 +1224,6 @@ function estimateSecurityLevel(securityMode: MessageSecurityMode, securityPolicy
|
|
|
1224
1224
|
* @private
|
|
1225
1225
|
*/
|
|
1226
1226
|
function _makeEndpointDescription(options: MakeEndpointDescriptionOptions, parent: OPCUAServerEndPoint): EndpointDescriptionEx {
|
|
1227
|
-
assert(Object.prototype.hasOwnProperty.call(options, "serverCertificateChain"));
|
|
1228
|
-
assert(!Object.prototype.hasOwnProperty.call(options, "serverCertificate"));
|
|
1229
|
-
assert(!!options.securityMode); // s.MessageSecurityMode
|
|
1230
|
-
assert(!!options.securityPolicy);
|
|
1231
|
-
assert(options.server !== null && typeof options.server === "object");
|
|
1232
|
-
assert(!!options.hostname && typeof options.hostname === "string");
|
|
1233
|
-
assert(typeof options.restricted === "boolean");
|
|
1234
1227
|
|
|
1235
1228
|
const u = (n: string) => getUniqueName(n, options.collection);
|
|
1236
1229
|
options.securityLevel =
|
|
@@ -1353,7 +1346,7 @@ function _makeEndpointDescription(options: MakeEndpointDescriptionOptions, paren
|
|
|
1353
1346
|
endpointUrl: "<to be evaluated at run time>", // options.endpointUrl,
|
|
1354
1347
|
|
|
1355
1348
|
server: undefined, // options.server,
|
|
1356
|
-
serverCertificate: options.serverCertificateChain,
|
|
1349
|
+
serverCertificate: options.serverCertificateChain.length > 0 ? combine_der(options.serverCertificateChain) : undefined,
|
|
1357
1350
|
|
|
1358
1351
|
securityMode: options.securityMode,
|
|
1359
1352
|
securityPolicyUri,
|