node-opcua-client 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/alarms_and_conditions/client_alarm_tools.d.ts +1 -1
- package/dist/alarms_and_conditions/client_alarm_tools.js +2 -2
- package/dist/alarms_and_conditions/client_alarm_tools.js.map +1 -1
- package/dist/alarms_and_conditions/client_tools.d.ts +3 -0
- package/dist/alarms_and_conditions/client_tools.js +2 -2
- package/dist/alarms_and_conditions/client_tools.js.map +1 -1
- package/dist/client_base.d.ts +47 -40
- package/dist/client_base.js +5 -6
- package/dist/client_base.js.map +1 -1
- package/dist/client_monitored_item.d.ts +7 -7
- package/dist/client_monitored_item.js.map +1 -1
- package/dist/client_monitored_item_base.d.ts +12 -13
- package/dist/client_monitored_item_group.d.ts +5 -5
- package/dist/client_monitored_item_toolbox.d.ts +6 -7
- package/dist/client_monitored_item_toolbox.js.map +1 -1
- package/dist/client_session.d.ts +19 -23
- package/dist/client_session.js.map +1 -1
- package/dist/client_session_keepalive_manager.d.ts +1 -1
- package/dist/client_session_keepalive_manager.js +6 -6
- package/dist/client_session_keepalive_manager.js.map +1 -1
- package/dist/client_subscription.d.ts +11 -12
- package/dist/client_subscription.js.map +1 -1
- package/dist/client_utils.d.ts +3 -3
- package/dist/client_utils.js.map +1 -1
- package/dist/common.d.ts +12 -12
- package/dist/index.d.ts +26 -27
- package/dist/index.js +65 -66
- package/dist/index.js.map +1 -1
- package/dist/opcua_client.d.ts +17 -19
- package/dist/opcua_client.js.map +1 -1
- package/dist/private/client_base_impl.d.ts +19 -18
- package/dist/private/client_base_impl.js +220 -192
- package/dist/private/client_base_impl.js.map +1 -1
- package/dist/private/client_monitored_item_group_impl.d.ts +4 -5
- package/dist/private/client_monitored_item_group_impl.js +1 -1
- package/dist/private/client_monitored_item_group_impl.js.map +1 -1
- package/dist/private/client_monitored_item_impl.d.ts +9 -10
- package/dist/private/client_monitored_item_impl.js.map +1 -1
- package/dist/private/client_publish_engine.d.ts +3 -3
- package/dist/private/client_publish_engine.js +6 -7
- package/dist/private/client_publish_engine.js.map +1 -1
- package/dist/private/client_session_impl.d.ts +24 -25
- package/dist/private/client_session_impl.js +14 -10
- package/dist/private/client_session_impl.js.map +1 -1
- package/dist/private/client_subscription_impl.d.ts +10 -11
- package/dist/private/client_subscription_impl.js +12 -11
- package/dist/private/client_subscription_impl.js.map +1 -1
- package/dist/private/i_private_client.d.ts +7 -7
- package/dist/private/opcua_client_impl.d.ts +12 -9
- package/dist/private/opcua_client_impl.js +58 -48
- package/dist/private/opcua_client_impl.js.map +1 -1
- package/dist/private/performance.js.map +1 -1
- package/dist/private/reconnection/client_publish_engine_reconnection.d.ts +1 -1
- package/dist/private/reconnection/client_publish_engine_reconnection.js +54 -43
- package/dist/private/reconnection/client_publish_engine_reconnection.js.map +1 -1
- package/dist/private/reconnection/client_reconnection.d.ts +1 -1
- package/dist/private/reconnection/client_subscription_reconnection.d.ts +1 -1
- package/dist/private/reconnection/client_subscription_reconnection.js +2 -2
- package/dist/private/reconnection/client_subscription_reconnection.js.map +1 -1
- package/dist/private/reconnection/reconnection.d.ts +4 -4
- package/dist/private/reconnection/reconnection.js +200 -281
- package/dist/private/reconnection/reconnection.js.map +1 -1
- package/dist/tools/findservers.d.ts +7 -2
- package/dist/tools/findservers.js +41 -53
- package/dist/tools/findservers.js.map +1 -1
- package/dist/tools/read_history_server_capabilities.d.ts +1 -1
- package/dist/tools/read_history_server_capabilities.js +9 -8
- package/dist/tools/read_history_server_capabilities.js.map +1 -1
- package/dist/user_identity_info.d.ts +1 -1
- package/dist/verify.js.map +1 -1
- package/package.json +45 -45
- package/source/alarms_and_conditions/client_alarm_tools.ts +14 -8
- package/source/alarms_and_conditions/client_tools.ts +7 -6
- package/source/client_base.ts +93 -79
- package/source/client_monitored_item.ts +7 -8
- package/source/client_monitored_item_base.ts +12 -14
- package/source/client_monitored_item_group.ts +5 -5
- package/source/client_monitored_item_toolbox.ts +13 -14
- package/source/client_session.ts +37 -40
- package/source/client_session_keepalive_manager.ts +7 -10
- package/source/client_subscription.ts +11 -12
- package/source/client_utils.ts +6 -6
- package/source/common.ts +12 -12
- package/source/index.ts +44 -40
- package/source/opcua_client.ts +24 -23
- package/source/private/client_base_impl.ts +329 -290
- package/source/private/client_monitored_item_group_impl.ts +10 -14
- package/source/private/client_monitored_item_impl.ts +17 -17
- package/source/private/client_publish_engine.ts +11 -12
- package/source/private/client_session_impl.ts +85 -82
- package/source/private/client_subscription_impl.ts +42 -41
- package/source/private/i_private_client.ts +8 -8
- package/source/private/opcua_client_impl.ts +118 -97
- package/source/private/performance.ts +2 -3
- package/source/private/reconnection/client_publish_engine_reconnection.ts +76 -68
- package/source/private/reconnection/client_reconnection.ts +1 -1
- package/source/private/reconnection/client_subscription_reconnection.ts +16 -13
- package/source/private/reconnection/reconnection.ts +307 -301
- package/source/tools/findservers.ts +43 -62
- package/source/tools/read_history_server_capabilities.ts +20 -22
- package/source/user_identity_info.ts +5 -5
- package/source/verify.ts +25 -25
|
@@ -2,75 +2,78 @@
|
|
|
2
2
|
* @module node-opcua-client-private
|
|
3
3
|
*/
|
|
4
4
|
// tslint:disable:no-unused-expression
|
|
5
|
-
import fs from "fs";
|
|
6
|
-
import path from "path";
|
|
7
|
-
|
|
8
|
-
import chalk from "chalk";
|
|
5
|
+
import fs from "node:fs";
|
|
6
|
+
import path from "node:path";
|
|
7
|
+
|
|
9
8
|
import { withLock } from "@ster5/global-mutex";
|
|
9
|
+
|
|
10
|
+
import chalk from "chalk";
|
|
10
11
|
import { assert } from "node-opcua-assert";
|
|
11
|
-
import {
|
|
12
|
-
import {
|
|
12
|
+
import { getDefaultCertificateManager, makeSubject, type OPCUACertificateManager } from "node-opcua-certificate-manager";
|
|
13
|
+
import { type IOPCUASecureObjectOptions, makeApplicationUrn, OPCUASecureObject } from "node-opcua-common";
|
|
14
|
+
import { type Certificate, makeSHA1Thumbprint, split_der } from "node-opcua-crypto/web";
|
|
13
15
|
import { installPeriodicClockAdjustment, periodicClockAdjustment, uninstallPeriodicClockAdjustment } from "node-opcua-date-time";
|
|
14
16
|
import { checkDebugFlag, make_debugLog, make_errorLog, make_warningLog } from "node-opcua-debug";
|
|
15
|
-
|
|
16
|
-
import { makeApplicationUrn } from "node-opcua-common";
|
|
17
17
|
import { getHostname } from "node-opcua-hostname";
|
|
18
|
-
import { IBasicTransportSettings, ResponseCallback } from "node-opcua-pseudo-session";
|
|
18
|
+
import type { IBasicTransportSettings, ResponseCallback } from "node-opcua-pseudo-session";
|
|
19
19
|
import {
|
|
20
20
|
ClientSecureChannelLayer,
|
|
21
|
+
type ConnectionStrategy,
|
|
22
|
+
type ConnectionStrategyOptions,
|
|
21
23
|
coerceConnectionStrategy,
|
|
22
24
|
coerceSecurityPolicy,
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
SecurityPolicy
|
|
25
|
+
type PerformTransactionCallback,
|
|
26
|
+
type Request as Request1,
|
|
27
|
+
type Response as Response1,
|
|
28
|
+
type SecurityPolicy
|
|
28
29
|
} from "node-opcua-secure-channel";
|
|
29
30
|
import {
|
|
30
31
|
FindServersOnNetworkRequest,
|
|
31
|
-
FindServersOnNetworkRequestOptions,
|
|
32
|
+
type FindServersOnNetworkRequestOptions,
|
|
32
33
|
FindServersOnNetworkResponse,
|
|
33
34
|
FindServersRequest,
|
|
34
35
|
FindServersResponse,
|
|
35
|
-
ServerOnNetwork
|
|
36
|
+
type ServerOnNetwork
|
|
36
37
|
} from "node-opcua-service-discovery";
|
|
37
38
|
import {
|
|
38
|
-
ApplicationDescription,
|
|
39
|
-
EndpointDescription,
|
|
39
|
+
type ApplicationDescription,
|
|
40
|
+
type EndpointDescription,
|
|
40
41
|
GetEndpointsRequest,
|
|
41
42
|
GetEndpointsResponse
|
|
42
43
|
} from "node-opcua-service-endpoints";
|
|
43
|
-
import { ChannelSecurityToken, coerceMessageSecurityMode, MessageSecurityMode } from "node-opcua-service-secure-channel";
|
|
44
|
-
import {
|
|
45
|
-
import {
|
|
46
|
-
|
|
47
|
-
import { getDefaultCertificateManager, makeSubject, OPCUACertificateManager } from "node-opcua-certificate-manager";
|
|
48
|
-
import { VerificationStatus } from "node-opcua-pki";
|
|
49
|
-
import { CloseSessionRequest, CloseSessionResponse } from "node-opcua-service-session";
|
|
50
|
-
import { Request, Response } from "../common";
|
|
51
|
-
|
|
44
|
+
import { type ChannelSecurityToken, coerceMessageSecurityMode, MessageSecurityMode } from "node-opcua-service-secure-channel";
|
|
45
|
+
import { CloseSessionRequest, type CloseSessionResponse } from "node-opcua-service-session";
|
|
46
|
+
import { type ErrorCallback, StatusCodes } from "node-opcua-status-code";
|
|
47
|
+
import { checkFileExistsAndIsNotEmpty, matchUri } from "node-opcua-utils";
|
|
52
48
|
import {
|
|
53
|
-
CreateSecureChannelCallbackFunc,
|
|
54
|
-
FindEndpointCallback,
|
|
55
|
-
FindEndpointOptions,
|
|
56
|
-
FindEndpointResult,
|
|
57
|
-
FindServersOnNetworkRequestLike,
|
|
58
|
-
FindServersRequestLike,
|
|
59
|
-
GetEndpointsOptions,
|
|
49
|
+
type CreateSecureChannelCallbackFunc,
|
|
50
|
+
type FindEndpointCallback,
|
|
51
|
+
type FindEndpointOptions,
|
|
52
|
+
type FindEndpointResult,
|
|
53
|
+
type FindServersOnNetworkRequestLike,
|
|
54
|
+
type FindServersRequestLike,
|
|
55
|
+
type GetEndpointsOptions,
|
|
60
56
|
OPCUAClientBase,
|
|
61
|
-
|
|
62
|
-
|
|
57
|
+
type OPCUAClientBaseEvents,
|
|
58
|
+
type OPCUAClientBaseOptions,
|
|
59
|
+
type TransportSettings
|
|
63
60
|
} from "../client_base";
|
|
64
|
-
import {
|
|
61
|
+
import type { Request, Response } from "../common";
|
|
62
|
+
import type { UserIdentityInfo } from "../user_identity_info";
|
|
65
63
|
import { performCertificateSanityCheck } from "../verify";
|
|
66
|
-
import { ClientSessionImpl } from "./client_session_impl";
|
|
67
|
-
import { IClientBase } from "./i_private_client";
|
|
68
|
-
import { waitUntilReconnectionIsCanceled } from "./reconnection/client_reconnection";
|
|
64
|
+
import type { ClientSessionImpl } from "./client_session_impl";
|
|
65
|
+
import type { IClientBase } from "./i_private_client";
|
|
69
66
|
|
|
70
67
|
const debugLog = make_debugLog(__filename);
|
|
71
68
|
const doDebug = checkDebugFlag(__filename);
|
|
72
69
|
const errorLog = make_errorLog(__filename);
|
|
73
70
|
const warningLog = make_warningLog(__filename);
|
|
71
|
+
|
|
72
|
+
function makeCertificateThumbPrint(certificate: Certificate | Certificate[] | null | undefined): Buffer | null {
|
|
73
|
+
if (!certificate) return null;
|
|
74
|
+
return makeSHA1Thumbprint(Array.isArray(certificate) ? certificate[0] : certificate);
|
|
75
|
+
}
|
|
76
|
+
|
|
74
77
|
const traceInternalState = false;
|
|
75
78
|
|
|
76
79
|
const defaultConnectionStrategy: ConnectionStrategyOptions = {
|
|
@@ -96,7 +99,7 @@ function __findEndpoint(this: ClientBaseImpl, endpointUrl: string, params: FindE
|
|
|
96
99
|
|
|
97
100
|
const securityMode = params.securityMode;
|
|
98
101
|
const securityPolicy = params.securityPolicy;
|
|
99
|
-
const
|
|
102
|
+
const _connectionStrategy = params.connectionStrategy;
|
|
100
103
|
const options: OPCUAClientBaseOptions = {
|
|
101
104
|
applicationName: params.applicationName,
|
|
102
105
|
applicationUri: params.applicationUri,
|
|
@@ -119,10 +122,12 @@ function __findEndpoint(this: ClientBaseImpl, endpointUrl: string, params: FindE
|
|
|
119
122
|
|
|
120
123
|
let selectedEndpoint: EndpointDescription | undefined;
|
|
121
124
|
const allEndpoints: EndpointDescription[] = [];
|
|
122
|
-
const
|
|
123
|
-
(
|
|
125
|
+
const step1_connect = (): Promise<void> => {
|
|
126
|
+
return new Promise<void>((resolve, reject) => {
|
|
124
127
|
// rebind backoff handler
|
|
125
|
-
masterClient.listeners("backoff").forEach((handler
|
|
128
|
+
masterClient.listeners("backoff").forEach((handler) => {
|
|
129
|
+
client.on("backoff", handler as unknown as (retryCount: number, delay: number) => void);
|
|
130
|
+
});
|
|
126
131
|
|
|
127
132
|
// c8 ignore next
|
|
128
133
|
if (doDebug) {
|
|
@@ -140,7 +145,6 @@ function __findEndpoint(this: ClientBaseImpl, endpointUrl: string, params: FindE
|
|
|
140
145
|
|
|
141
146
|
client.connect(endpointUrl, (err?: Error) => {
|
|
142
147
|
if (err) {
|
|
143
|
-
// let's improve the error message with meaningful info
|
|
144
148
|
err.message =
|
|
145
149
|
"Fail to connect to server at " +
|
|
146
150
|
endpointUrl +
|
|
@@ -149,20 +153,23 @@ function __findEndpoint(this: ClientBaseImpl, endpointUrl: string, params: FindE
|
|
|
149
153
|
err.message +
|
|
150
154
|
")";
|
|
151
155
|
warningLog(err.message);
|
|
156
|
+
return reject(err);
|
|
152
157
|
}
|
|
153
|
-
|
|
158
|
+
resolve();
|
|
154
159
|
});
|
|
155
|
-
}
|
|
160
|
+
});
|
|
161
|
+
};
|
|
156
162
|
|
|
157
|
-
|
|
163
|
+
const step2_getEndpoints = (): Promise<void> => {
|
|
164
|
+
return new Promise<void>((resolve, reject) => {
|
|
158
165
|
client.getEndpoints((err: Error | null, endpoints?: EndpointDescription[]) => {
|
|
159
166
|
if (err) {
|
|
160
|
-
err.message =
|
|
161
|
-
return
|
|
167
|
+
err.message = `error in getEndpoints \n${err.message}`;
|
|
168
|
+
return reject(err);
|
|
162
169
|
}
|
|
163
170
|
// c8 ignore next
|
|
164
171
|
if (!endpoints) {
|
|
165
|
-
return
|
|
172
|
+
return reject(new Error("Internal Error"));
|
|
166
173
|
}
|
|
167
174
|
|
|
168
175
|
for (const endpoint of endpoints) {
|
|
@@ -177,55 +184,51 @@ function __findEndpoint(this: ClientBaseImpl, endpointUrl: string, params: FindE
|
|
|
177
184
|
selectedEndpoint = endpoint; // found it
|
|
178
185
|
}
|
|
179
186
|
}
|
|
180
|
-
|
|
187
|
+
resolve();
|
|
181
188
|
});
|
|
182
|
-
}
|
|
189
|
+
});
|
|
190
|
+
};
|
|
183
191
|
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
192
|
+
const step3_disconnect = (): Promise<void> => {
|
|
193
|
+
return new Promise<void>((resolve) => {
|
|
194
|
+
client.disconnect(() => resolve());
|
|
195
|
+
});
|
|
196
|
+
};
|
|
188
197
|
|
|
189
|
-
|
|
190
|
-
|
|
198
|
+
step1_connect()
|
|
199
|
+
.then(() => step2_getEndpoints())
|
|
200
|
+
.then(() => step3_disconnect())
|
|
201
|
+
.then(() => {
|
|
202
|
+
if (!selectedEndpoint) {
|
|
203
|
+
return callback(
|
|
204
|
+
new Error(
|
|
205
|
+
"Cannot find an Endpoint matching " +
|
|
206
|
+
" security mode: " +
|
|
207
|
+
securityMode.toString() +
|
|
208
|
+
" policy: " +
|
|
209
|
+
securityPolicy.toString()
|
|
210
|
+
)
|
|
211
|
+
);
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
// c8 ignore next
|
|
215
|
+
if (doDebug) {
|
|
216
|
+
debugLog(chalk.bgWhite.red("xxxxxxxxxxxxxxxxxxxxx => selected EndPoint = "), selectedEndpoint.toString());
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
callback(null, { endpoints: allEndpoints, selectedEndpoint });
|
|
220
|
+
})
|
|
221
|
+
.catch((err) => {
|
|
191
222
|
client.disconnect(() => {
|
|
192
223
|
callback(err);
|
|
193
224
|
});
|
|
194
|
-
|
|
195
|
-
}
|
|
196
|
-
|
|
197
|
-
if (!selectedEndpoint) {
|
|
198
|
-
return callback(
|
|
199
|
-
new Error(
|
|
200
|
-
"Cannot find an Endpoint matching " +
|
|
201
|
-
" security mode: " +
|
|
202
|
-
securityMode.toString() +
|
|
203
|
-
" policy: " +
|
|
204
|
-
securityPolicy.toString()
|
|
205
|
-
)
|
|
206
|
-
);
|
|
207
|
-
}
|
|
208
|
-
|
|
209
|
-
// c8 ignore next
|
|
210
|
-
if (doDebug) {
|
|
211
|
-
debugLog(chalk.bgWhite.red("xxxxxxxxxxxxxxxxxxxxx => selected EndPoint = "), selectedEndpoint.toString());
|
|
212
|
-
}
|
|
213
|
-
|
|
214
|
-
const result = {
|
|
215
|
-
endpoints: allEndpoints,
|
|
216
|
-
selectedEndpoint
|
|
217
|
-
};
|
|
218
|
-
|
|
219
|
-
callback(null, result);
|
|
220
|
-
});
|
|
225
|
+
});
|
|
221
226
|
}
|
|
222
227
|
|
|
223
228
|
/**
|
|
224
229
|
* check if certificate is trusted or untrusted
|
|
225
230
|
*/
|
|
226
|
-
async function _verify_serverCertificate(
|
|
227
|
-
certificateManager: OPCUACertificateManager,
|
|
228
|
-
serverCertificate: Certificate) {
|
|
231
|
+
async function _verify_serverCertificate(certificateManager: OPCUACertificateManager, serverCertificate: Certificate) {
|
|
229
232
|
const status = await certificateManager.checkCertificate(serverCertificate);
|
|
230
233
|
if (status !== StatusCodes.Good) {
|
|
231
234
|
// c8 ignore next
|
|
@@ -234,9 +237,9 @@ async function _verify_serverCertificate(
|
|
|
234
237
|
const status1 = await certificateManager.verifyCertificate(serverCertificate);
|
|
235
238
|
debugLog(status1);
|
|
236
239
|
}
|
|
237
|
-
warningLog("serverCertificate = ",
|
|
240
|
+
warningLog("serverCertificate = ", makeCertificateThumbPrint(serverCertificate)?.toString("hex") || "none");
|
|
238
241
|
warningLog("serverCertificate = ", serverCertificate.toString("base64"));
|
|
239
|
-
throw new Error(
|
|
242
|
+
throw new Error(`server Certificate verification failed with err ${status?.toString()}`);
|
|
240
243
|
}
|
|
241
244
|
}
|
|
242
245
|
|
|
@@ -290,7 +293,9 @@ let g_ClientCounter = 0;
|
|
|
290
293
|
* @internal
|
|
291
294
|
*/
|
|
292
295
|
// tslint:disable-next-line: max-classes-per-file
|
|
293
|
-
export class ClientBaseImpl extends
|
|
296
|
+
export class ClientBaseImpl<Events extends OPCUAClientBaseEvents = OPCUAClientBaseEvents>
|
|
297
|
+
extends OPCUASecureObject<Events>
|
|
298
|
+
implements OPCUAClientBase<Events>, IClientBase {
|
|
294
299
|
/**
|
|
295
300
|
* total number of requests that been canceled due to timeout
|
|
296
301
|
*/
|
|
@@ -317,7 +322,7 @@ export class ClientBaseImpl extends OPCUASecureObject implements OPCUAClientBase
|
|
|
317
322
|
*/
|
|
318
323
|
get isReconnecting(): boolean {
|
|
319
324
|
return (
|
|
320
|
-
!!
|
|
325
|
+
!!this._secureChannel?.isConnecting ||
|
|
321
326
|
this._internalState === "reconnecting_newchannel_connected" ||
|
|
322
327
|
this._internalState === "reconnecting"
|
|
323
328
|
);
|
|
@@ -346,7 +351,7 @@ export class ClientBaseImpl extends OPCUASecureObject implements OPCUAClientBase
|
|
|
346
351
|
|
|
347
352
|
public securityMode: MessageSecurityMode;
|
|
348
353
|
public securityPolicy: SecurityPolicy;
|
|
349
|
-
public serverCertificate?: Certificate;
|
|
354
|
+
public serverCertificate?: Certificate | Certificate[];
|
|
350
355
|
public clientName: string;
|
|
351
356
|
public protocolVersion: 0;
|
|
352
357
|
public defaultSecureTokenLifetime: number;
|
|
@@ -412,11 +417,15 @@ export class ClientBaseImpl extends OPCUASecureObject implements OPCUAClientBase
|
|
|
412
417
|
|
|
413
418
|
this._internalState = internalState;
|
|
414
419
|
}
|
|
415
|
-
public emit(eventName:
|
|
420
|
+
public emit<K>(eventName: K, ...others: unknown[]): boolean {
|
|
416
421
|
// c8 ignore next
|
|
417
422
|
if (doDebug) {
|
|
418
|
-
debugLog(
|
|
423
|
+
debugLog(
|
|
424
|
+
chalk.cyan(` Client ${this._instanceNumber} ${this.clientName} emitting `),
|
|
425
|
+
chalk.magentaBright(eventName as string)
|
|
426
|
+
);
|
|
419
427
|
}
|
|
428
|
+
// @ts-expect-error
|
|
420
429
|
return super.emit(eventName, ...others);
|
|
421
430
|
}
|
|
422
431
|
constructor(options?: OPCUAClientBaseOptions) {
|
|
@@ -464,9 +473,10 @@ export class ClientBaseImpl extends OPCUASecureObject implements OPCUAClientBase
|
|
|
464
473
|
this.defaultTransactionTimeout = options.defaultTransactionTimeout;
|
|
465
474
|
|
|
466
475
|
this.tokenRenewalInterval = options.tokenRenewalInterval || 0;
|
|
467
|
-
assert(isFinite(this.tokenRenewalInterval) && this.tokenRenewalInterval >= 0);
|
|
476
|
+
assert(Number.isFinite(this.tokenRenewalInterval) && this.tokenRenewalInterval >= 0);
|
|
468
477
|
this.securityMode = coerceMessageSecurityMode(options.securityMode);
|
|
469
478
|
this.securityPolicy = coerceSecurityPolicy(options.securityPolicy);
|
|
479
|
+
|
|
470
480
|
this.serverCertificate = options.serverCertificate;
|
|
471
481
|
|
|
472
482
|
this.keepSessionAlive = typeof options.keepSessionAlive === "boolean" ? options.keepSessionAlive : false;
|
|
@@ -517,9 +527,6 @@ export class ClientBaseImpl extends OPCUASecureObject implements OPCUAClientBase
|
|
|
517
527
|
this._secureChannel = null;
|
|
518
528
|
callback();
|
|
519
529
|
});
|
|
520
|
-
this.once("reconnection_canceled", () => {
|
|
521
|
-
/* empty */
|
|
522
|
-
});
|
|
523
530
|
}
|
|
524
531
|
|
|
525
532
|
public _recreate_secure_channel(callback: ErrorCallback): void {
|
|
@@ -527,7 +534,8 @@ export class ClientBaseImpl extends OPCUASecureObject implements OPCUAClientBase
|
|
|
527
534
|
|
|
528
535
|
if (!this.knowsServerEndpoint) {
|
|
529
536
|
debugLog("Cannot reconnect , server endpoint is unknown");
|
|
530
|
-
|
|
537
|
+
callback(new Error("Cannot reconnect, server endpoint is unknown - this.knowsServerEndpoint = false"));
|
|
538
|
+
return;
|
|
531
539
|
}
|
|
532
540
|
assert(this.knowsServerEndpoint);
|
|
533
541
|
|
|
@@ -548,7 +556,7 @@ export class ClientBaseImpl extends OPCUASecureObject implements OPCUAClientBase
|
|
|
548
556
|
const _when_reconnectionIsCanceled = (callback: ErrorCallback) => {
|
|
549
557
|
doDebug && debugLog("attempt to recreate a new secure channel : suspended because reconnection is canceled !");
|
|
550
558
|
this.emit("reconnection_canceled");
|
|
551
|
-
return callback(new Error(
|
|
559
|
+
return callback(new Error(`Reconnection has been canceled - ${this.clientName}`));
|
|
552
560
|
};
|
|
553
561
|
|
|
554
562
|
const _failAndRetry = (err: Error, message: string, callback: ErrorCallback) => {
|
|
@@ -597,20 +605,21 @@ export class ClientBaseImpl extends OPCUASecureObject implements OPCUAClientBase
|
|
|
597
605
|
if (err.message.match(/ECONNREFUSED|ECONNABORTED|ETIMEDOUT/)) {
|
|
598
606
|
return _failAndRetry(
|
|
599
607
|
err,
|
|
600
|
-
|
|
608
|
+
`create secure channel failed with ECONNREFUSED|ECONNABORTED|ETIMEDOUT\n${err.message}`,
|
|
601
609
|
callback
|
|
602
610
|
);
|
|
603
611
|
}
|
|
604
612
|
|
|
605
613
|
if (err.message.match("Backoff aborted.")) {
|
|
606
|
-
|
|
614
|
+
_failAndRetry(err, "cannot create secure channel (backoff aborted)", callback);
|
|
615
|
+
return;
|
|
607
616
|
}
|
|
608
617
|
|
|
609
618
|
if (
|
|
610
|
-
err
|
|
611
|
-
err
|
|
619
|
+
err?.message.match("BadCertificateInvalid") ||
|
|
620
|
+
err?.message.match(/socket has been disconnected by third party/)
|
|
612
621
|
) {
|
|
613
|
-
// it is possible also that hte server has shutdown innapropriately the connection
|
|
622
|
+
// it is possible also that hte server has shutdown innapropriately the connection
|
|
614
623
|
warningLog(
|
|
615
624
|
"the server certificate has changed, we need to retrieve server certificate again: ",
|
|
616
625
|
err.message
|
|
@@ -618,7 +627,7 @@ export class ClientBaseImpl extends OPCUASecureObject implements OPCUAClientBase
|
|
|
618
627
|
const oldServerCertificate = this.serverCertificate;
|
|
619
628
|
warningLog(
|
|
620
629
|
"old server certificate ",
|
|
621
|
-
|
|
630
|
+
makeCertificateThumbPrint(oldServerCertificate)?.toString("hex") || "undefined"
|
|
622
631
|
);
|
|
623
632
|
// the server may have shut down the channel because its certificate
|
|
624
633
|
// has changed ....
|
|
@@ -627,11 +636,14 @@ export class ClientBaseImpl extends OPCUASecureObject implements OPCUAClientBase
|
|
|
627
636
|
if (err1) {
|
|
628
637
|
return _failAndRetry(err1, "Failing to fetch new server certificate", callback);
|
|
629
638
|
}
|
|
630
|
-
const newServerCertificate = this.serverCertificate
|
|
631
|
-
warningLog(
|
|
639
|
+
const newServerCertificate = this.serverCertificate;
|
|
640
|
+
warningLog(
|
|
641
|
+
"new server certificate ",
|
|
642
|
+
makeCertificateThumbPrint(newServerCertificate)?.toString("hex") || "none"
|
|
643
|
+
);
|
|
632
644
|
|
|
633
|
-
const sha1Old =
|
|
634
|
-
const sha1New =
|
|
645
|
+
const sha1Old = makeCertificateThumbPrint(oldServerCertificate)?.toString("hex") || null;
|
|
646
|
+
const sha1New = makeCertificateThumbPrint(newServerCertificate)?.toString("hex") || null;
|
|
635
647
|
if (sha1Old === sha1New) {
|
|
636
648
|
warningLog("server certificate has not changed, but was expected to have changed");
|
|
637
649
|
return _failAndRetry(
|
|
@@ -699,60 +711,65 @@ export class ClientBaseImpl extends OPCUASecureObject implements OPCUAClientBase
|
|
|
699
711
|
|
|
700
712
|
this.emit("secure_channel_created", secureChannel);
|
|
701
713
|
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
(innerCallback: ErrorCallback) => {
|
|
706
|
-
debugLog("_internal_create_secure_channel before secureChannel.create");
|
|
714
|
+
const step2_openSecureChannel = (): Promise<void> => {
|
|
715
|
+
return new Promise<void>((resolve, reject) => {
|
|
716
|
+
debugLog("_internal_create_secure_channel before secureChannel.create");
|
|
707
717
|
|
|
708
|
-
|
|
709
|
-
|
|
718
|
+
secureChannel.create(this.endpointUrl, (err?: Error) => {
|
|
719
|
+
debugLog("_internal_create_secure_channel after secureChannel.create");
|
|
720
|
+
if (!this._secureChannel) {
|
|
721
|
+
debugLog("_secureChannel has been closed during the transaction !");
|
|
722
|
+
return reject(new Error("Secure Channel Closed"));
|
|
723
|
+
}
|
|
724
|
+
if (err) {
|
|
725
|
+
return reject(err);
|
|
726
|
+
}
|
|
727
|
+
this._install_secure_channel_event_handlers(secureChannel);
|
|
728
|
+
resolve();
|
|
729
|
+
});
|
|
730
|
+
});
|
|
731
|
+
};
|
|
732
|
+
|
|
733
|
+
const step3_getEndpoints = (): Promise<void> => {
|
|
734
|
+
return new Promise<void>((resolve, reject) => {
|
|
735
|
+
assert(this._secureChannel !== null);
|
|
736
|
+
if (!this.knowsServerEndpoint) {
|
|
737
|
+
this._setInternalState("connecting");
|
|
738
|
+
|
|
739
|
+
this.getEndpoints((err: Error | null /*, endpoints?: EndpointDescription[]*/) => {
|
|
710
740
|
if (!this._secureChannel) {
|
|
711
|
-
debugLog("_secureChannel has been closed during the transaction !");
|
|
712
|
-
return
|
|
741
|
+
debugLog("_secureChannel has been closed during the transaction ! (while getEndpoints)");
|
|
742
|
+
return reject(new Error("Secure Channel Closed"));
|
|
713
743
|
}
|
|
714
|
-
if (
|
|
715
|
-
|
|
744
|
+
if (err) {
|
|
745
|
+
return reject(err);
|
|
716
746
|
}
|
|
717
|
-
|
|
747
|
+
resolve();
|
|
718
748
|
});
|
|
719
|
-
}
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
assert(this._secureChannel !== null);
|
|
723
|
-
if (!this.knowsServerEndpoint) {
|
|
724
|
-
this._setInternalState("connecting");
|
|
725
|
-
|
|
726
|
-
this.getEndpoints((err: Error | null /*, endpoints?: EndpointDescription[]*/) => {
|
|
727
|
-
if (!this._secureChannel) {
|
|
728
|
-
debugLog("_secureChannel has been closed during the transaction ! (while getEndpoints)");
|
|
729
|
-
return innerCallback(new Error("Secure Channel Closed"));
|
|
730
|
-
}
|
|
731
|
-
innerCallback(err ? err : undefined);
|
|
732
|
-
});
|
|
733
|
-
} else {
|
|
734
|
-
// end points are already known
|
|
735
|
-
innerCallback();
|
|
736
|
-
}
|
|
749
|
+
} else {
|
|
750
|
+
// end points are already known
|
|
751
|
+
resolve();
|
|
737
752
|
}
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
753
|
+
});
|
|
754
|
+
};
|
|
755
|
+
|
|
756
|
+
step2_openSecureChannel()
|
|
757
|
+
.then(() => step3_getEndpoints())
|
|
758
|
+
.then(() => {
|
|
759
|
+
assert(this._secureChannel !== null);
|
|
760
|
+
callback(null, secureChannel);
|
|
761
|
+
})
|
|
762
|
+
.catch((err) => {
|
|
763
|
+
doDebug && debugLog(this.clientName, " : Inner create secure channel has failed", err.message);
|
|
764
|
+
if (this._secureChannel) {
|
|
765
|
+
this._secureChannel.abortConnection(() => {
|
|
766
|
+
this._destroy_secure_channel();
|
|
748
767
|
callback(err);
|
|
749
|
-
}
|
|
768
|
+
});
|
|
750
769
|
} else {
|
|
751
|
-
|
|
752
|
-
callback(null, secureChannel);
|
|
770
|
+
callback(err);
|
|
753
771
|
}
|
|
754
|
-
}
|
|
755
|
-
);
|
|
772
|
+
});
|
|
756
773
|
}
|
|
757
774
|
|
|
758
775
|
static async createCertificate(
|
|
@@ -776,19 +793,19 @@ export class ClientBaseImpl extends OPCUASecureObject implements OPCUAClientBase
|
|
|
776
793
|
}
|
|
777
794
|
// c8 ignore next
|
|
778
795
|
if (!fs.existsSync(certificateFile)) {
|
|
779
|
-
throw new Error(
|
|
796
|
+
throw new Error(` cannot locate certificate file ${certificateFile}`);
|
|
780
797
|
}
|
|
781
798
|
}
|
|
782
799
|
|
|
783
800
|
public async createDefaultCertificate(): Promise<void> {
|
|
784
801
|
// c8 ignore next
|
|
785
|
-
if ((this as
|
|
802
|
+
if ((this as unknown as { _inCreateDefaultCertificate: boolean })._inCreateDefaultCertificate) {
|
|
786
803
|
errorLog("Internal error : re-entrancy in createDefaultCertificate!");
|
|
787
804
|
}
|
|
788
|
-
(this as
|
|
805
|
+
(this as unknown as { _inCreateDefaultCertificate: boolean })._inCreateDefaultCertificate = true;
|
|
789
806
|
|
|
790
807
|
if (!checkFileExistsAndIsNotEmpty(this.certificateFile)) {
|
|
791
|
-
await withLock({ fileToLock: this.certificateFile
|
|
808
|
+
await withLock({ fileToLock: `${this.certificateFile}.mutex` }, async () => {
|
|
792
809
|
if (checkFileExistsAndIsNotEmpty(this.certificateFile)) {
|
|
793
810
|
// the file may have been created in between
|
|
794
811
|
return;
|
|
@@ -804,11 +821,11 @@ export class ClientBaseImpl extends OPCUASecureObject implements OPCUAClientBase
|
|
|
804
821
|
debugLog("privateKey = ", this.privateKeyFile);
|
|
805
822
|
debugLog(" = ", this.clientCertificateManager.privateKey);
|
|
806
823
|
debugLog("certificateFile = ", this.certificateFile);
|
|
807
|
-
const
|
|
808
|
-
const
|
|
824
|
+
const _certificate = this.getCertificate();
|
|
825
|
+
const _privateKey = this.getPrivateKey();
|
|
809
826
|
});
|
|
810
827
|
}
|
|
811
|
-
(this as
|
|
828
|
+
(this as unknown as { _inCreateDefaultCertificate: boolean })._inCreateDefaultCertificate = false;
|
|
812
829
|
}
|
|
813
830
|
|
|
814
831
|
protected _getBuiltApplicationUri(): string {
|
|
@@ -833,7 +850,7 @@ export class ClientBaseImpl extends OPCUASecureObject implements OPCUAClientBase
|
|
|
833
850
|
await this.createDefaultCertificate();
|
|
834
851
|
// c8 ignore next
|
|
835
852
|
if (!fs.existsSync(this.privateKeyFile)) {
|
|
836
|
-
throw new Error(
|
|
853
|
+
throw new Error(` cannot locate private key file ${this.privateKeyFile}`);
|
|
837
854
|
}
|
|
838
855
|
if (this.isUnusable()) return;
|
|
839
856
|
|
|
@@ -850,13 +867,13 @@ export class ClientBaseImpl extends OPCUASecureObject implements OPCUAClientBase
|
|
|
850
867
|
debugLog(err.message);
|
|
851
868
|
this.emit("connection_failed", err);
|
|
852
869
|
this._setInternalState("disconnected");
|
|
853
|
-
|
|
870
|
+
callback(err);
|
|
854
871
|
}
|
|
855
872
|
private _handleDisconnectionWhileConnecting(err: Error, callback: ErrorCallback) {
|
|
856
873
|
debugLog(err.message);
|
|
857
874
|
this.emit("connection_failed", err);
|
|
858
875
|
this._setInternalState("disconnected");
|
|
859
|
-
|
|
876
|
+
callback(err);
|
|
860
877
|
}
|
|
861
878
|
private _handleSuccessfulConnection(callback: ErrorCallback) {
|
|
862
879
|
debugLog(" Connected successfully to ", this.endpointUrl);
|
|
@@ -870,12 +887,12 @@ export class ClientBaseImpl extends OPCUASecureObject implements OPCUAClientBase
|
|
|
870
887
|
*/
|
|
871
888
|
public connect(endpointUrl: string): Promise<void>;
|
|
872
889
|
public connect(endpointUrl: string, callback: ErrorCallback): void;
|
|
873
|
-
public connect(...args:
|
|
890
|
+
public connect(...args: unknown[]): Promise<void> | void {
|
|
874
891
|
const endpointUrl = args[0];
|
|
875
|
-
const callback = args[1];
|
|
892
|
+
const callback = args[1] as ErrorCallback;
|
|
876
893
|
assert(typeof callback === "function", "expecting a callback");
|
|
877
894
|
if (typeof endpointUrl !== "string" || endpointUrl.length <= 0) {
|
|
878
|
-
errorLog(
|
|
895
|
+
errorLog(`[NODE-OPCUA-E03] OPCUAClient#connect expects a valid endpoint : ${endpointUrl}`);
|
|
879
896
|
callback(new Error("Invalid endpoint"));
|
|
880
897
|
return;
|
|
881
898
|
}
|
|
@@ -916,7 +933,7 @@ export class ClientBaseImpl extends OPCUASecureObject implements OPCUAClientBase
|
|
|
916
933
|
}
|
|
917
934
|
if (forceEndpointDiscoveryOnConnect) {
|
|
918
935
|
debugLog("connecting with adjusted endpoint : ", adjustedEndpointUrl, " was =", endpointUrl);
|
|
919
|
-
this._connectStep2(adjustedEndpointUrl
|
|
936
|
+
this._connectStep2(adjustedEndpointUrl || "", callback);
|
|
920
937
|
} else {
|
|
921
938
|
debugLog("connecting with endpoint : ", endpointUrl);
|
|
922
939
|
this._connectStep2(endpointUrl, callback);
|
|
@@ -955,15 +972,13 @@ export class ClientBaseImpl extends OPCUASecureObject implements OPCUAClientBase
|
|
|
955
972
|
}
|
|
956
973
|
debugLog(chalk.red("SecureChannel creation has failed with error :", err.message));
|
|
957
974
|
if (err.message.match(/ECONNABORTED/)) {
|
|
958
|
-
debugLog(chalk.yellow(
|
|
975
|
+
debugLog(chalk.yellow(`- The client cannot to :${endpointUrl}. Connection has been aborted.`));
|
|
959
976
|
err = new Error("The connection has been aborted");
|
|
960
977
|
this._handleUnrecoverableConnectionFailure(err, callback);
|
|
961
978
|
} else if (err.message.match(/ECONNREF/)) {
|
|
962
|
-
debugLog(chalk.yellow(
|
|
979
|
+
debugLog(chalk.yellow(`- The client cannot to :${endpointUrl}. Server is not reachable.`));
|
|
963
980
|
err = new Error(
|
|
964
|
-
|
|
965
|
-
endpointUrl +
|
|
966
|
-
" .\n" +
|
|
981
|
+
`The connection cannot be established with server ${endpointUrl} .\n` +
|
|
967
982
|
"Please check that the server is up and running or your network configuration.\n" +
|
|
968
983
|
"Err = (" +
|
|
969
984
|
err.message +
|
|
@@ -974,7 +989,7 @@ export class ClientBaseImpl extends OPCUASecureObject implements OPCUAClientBase
|
|
|
974
989
|
/* */
|
|
975
990
|
this._handleDisconnectionWhileConnecting(err, callback);
|
|
976
991
|
} else {
|
|
977
|
-
err = new Error(
|
|
992
|
+
err = new Error(`The connection may have been rejected by server,\n Err = (${err.message})`);
|
|
978
993
|
this._handleUnrecoverableConnectionFailure(err, callback);
|
|
979
994
|
}
|
|
980
995
|
}
|
|
@@ -985,9 +1000,10 @@ export class ClientBaseImpl extends OPCUASecureObject implements OPCUAClientBase
|
|
|
985
1000
|
if (!this._secureChannel) {
|
|
986
1001
|
// this may happen if the Server has closed the connection abruptly for some unknown reason
|
|
987
1002
|
// or if the tcp connection has been broken.
|
|
988
|
-
|
|
1003
|
+
callback(
|
|
989
1004
|
new Error("performMessageTransaction: No SecureChannel , connection may have been canceled abruptly by server")
|
|
990
1005
|
);
|
|
1006
|
+
return;
|
|
991
1007
|
}
|
|
992
1008
|
if (
|
|
993
1009
|
this._internalState !== "connected" &&
|
|
@@ -995,7 +1011,7 @@ export class ClientBaseImpl extends OPCUASecureObject implements OPCUAClientBase
|
|
|
995
1011
|
this._internalState !== "connecting" &&
|
|
996
1012
|
this._internalState !== "reconnecting"
|
|
997
1013
|
) {
|
|
998
|
-
|
|
1014
|
+
callback(
|
|
999
1015
|
new Error(
|
|
1000
1016
|
"performMessageTransaction: Invalid client state = " +
|
|
1001
1017
|
this._internalState +
|
|
@@ -1003,12 +1019,13 @@ export class ClientBaseImpl extends OPCUASecureObject implements OPCUAClientBase
|
|
|
1003
1019
|
request.schema.name
|
|
1004
1020
|
)
|
|
1005
1021
|
);
|
|
1022
|
+
return;
|
|
1006
1023
|
}
|
|
1007
1024
|
assert(this._secureChannel);
|
|
1008
1025
|
assert(request);
|
|
1009
1026
|
assert(request.requestHeader);
|
|
1010
1027
|
assert(typeof callback === "function");
|
|
1011
|
-
this._secureChannel.performMessageTransaction(request, callback as
|
|
1028
|
+
this._secureChannel.performMessageTransaction(request, callback as unknown as PerformTransactionCallback);
|
|
1012
1029
|
}
|
|
1013
1030
|
|
|
1014
1031
|
/**
|
|
@@ -1054,9 +1071,10 @@ export class ClientBaseImpl extends OPCUASecureObject implements OPCUAClientBase
|
|
|
1054
1071
|
public async getEndpoints(options?: GetEndpointsOptions): Promise<EndpointDescription[]>;
|
|
1055
1072
|
public getEndpoints(options: GetEndpointsOptions, callback: ResponseCallback<EndpointDescription[]>): void;
|
|
1056
1073
|
public getEndpoints(callback: ResponseCallback<EndpointDescription[]>): void;
|
|
1057
|
-
public getEndpoints(...args:
|
|
1074
|
+
public getEndpoints(...args: unknown[]): Promise<EndpointDescription[]> | undefined {
|
|
1058
1075
|
if (args.length === 1) {
|
|
1059
|
-
|
|
1076
|
+
this.getEndpoints({} as GetEndpointsOptions, args[0] as unknown as ResponseCallback<EndpointDescription[]>);
|
|
1077
|
+
return;
|
|
1060
1078
|
}
|
|
1061
1079
|
const options = args[0] as GetEndpointsOptions;
|
|
1062
1080
|
const callback = args[1] as ResponseCallback<EndpointDescription[]>;
|
|
@@ -1076,18 +1094,21 @@ export class ClientBaseImpl extends OPCUASecureObject implements OPCUAClientBase
|
|
|
1076
1094
|
|
|
1077
1095
|
this.performMessageTransaction(request, (err: Error | null, response?: Response) => {
|
|
1078
1096
|
if (err) {
|
|
1079
|
-
|
|
1097
|
+
callback(err);
|
|
1098
|
+
return;
|
|
1080
1099
|
}
|
|
1081
1100
|
this._serverEndpoints = [];
|
|
1082
1101
|
// c8 ignore next
|
|
1083
1102
|
if (!response || !(response instanceof GetEndpointsResponse)) {
|
|
1084
|
-
|
|
1103
|
+
callback(new Error("Internal Error"));
|
|
1104
|
+
return;
|
|
1085
1105
|
}
|
|
1086
|
-
if (response
|
|
1106
|
+
if (response?.endpoints) {
|
|
1087
1107
|
this._serverEndpoints = response.endpoints;
|
|
1088
1108
|
}
|
|
1089
1109
|
callback(null, this._serverEndpoints);
|
|
1090
1110
|
});
|
|
1111
|
+
return;
|
|
1091
1112
|
}
|
|
1092
1113
|
|
|
1093
1114
|
/**
|
|
@@ -1095,7 +1116,7 @@ export class ClientBaseImpl extends OPCUASecureObject implements OPCUAClientBase
|
|
|
1095
1116
|
*/
|
|
1096
1117
|
public getEndpointsRequest(options: GetEndpointsOptions, callback: ResponseCallback<EndpointDescription[]>): void {
|
|
1097
1118
|
warningLog("note: ClientBaseImpl#getEndpointsRequest is deprecated, use ClientBaseImpl#getEndpoints instead");
|
|
1098
|
-
|
|
1119
|
+
this.getEndpoints(options, callback);
|
|
1099
1120
|
}
|
|
1100
1121
|
|
|
1101
1122
|
/**
|
|
@@ -1104,9 +1125,13 @@ export class ClientBaseImpl extends OPCUASecureObject implements OPCUAClientBase
|
|
|
1104
1125
|
public findServers(options?: FindServersRequestLike): Promise<ApplicationDescription[]>;
|
|
1105
1126
|
public findServers(options: FindServersRequestLike, callback: ResponseCallback<ApplicationDescription[]>): void;
|
|
1106
1127
|
public findServers(callback: ResponseCallback<ApplicationDescription[]>): void;
|
|
1107
|
-
public findServers(...args:
|
|
1128
|
+
public findServers(...args: unknown[]): Promise<ApplicationDescription[]> | undefined {
|
|
1108
1129
|
if (args.length === 1) {
|
|
1109
|
-
|
|
1130
|
+
if (typeof args[0] === "function") {
|
|
1131
|
+
this.findServers({} as FindServersRequestLike, args[0] as ResponseCallback<ApplicationDescription[]>);
|
|
1132
|
+
return;
|
|
1133
|
+
}
|
|
1134
|
+
throw new Error("Invalid arguments");
|
|
1110
1135
|
}
|
|
1111
1136
|
const options = args[0] as FindServersRequestLike;
|
|
1112
1137
|
const callback = args[1] as ResponseCallback<ApplicationDescription[]>;
|
|
@@ -1119,24 +1144,28 @@ export class ClientBaseImpl extends OPCUASecureObject implements OPCUAClientBase
|
|
|
1119
1144
|
|
|
1120
1145
|
this.performMessageTransaction(request, (err: Error | null, response?: Response) => {
|
|
1121
1146
|
if (err) {
|
|
1122
|
-
|
|
1147
|
+
callback(err);
|
|
1148
|
+
return;
|
|
1123
1149
|
}
|
|
1124
1150
|
/* c8 ignore next */
|
|
1125
1151
|
if (!response || !(response instanceof FindServersResponse)) {
|
|
1126
|
-
|
|
1152
|
+
callback(new Error("Internal Error"));
|
|
1153
|
+
return;
|
|
1127
1154
|
}
|
|
1128
1155
|
response.servers = response.servers || [];
|
|
1129
1156
|
|
|
1130
1157
|
callback(null, response.servers);
|
|
1131
1158
|
});
|
|
1159
|
+
return undefined;
|
|
1132
1160
|
}
|
|
1133
1161
|
|
|
1134
1162
|
public findServersOnNetwork(options?: FindServersOnNetworkRequestLike): Promise<ServerOnNetwork[]>;
|
|
1135
1163
|
public findServersOnNetwork(callback: ResponseCallback<ServerOnNetwork[]>): void;
|
|
1136
1164
|
public findServersOnNetwork(options: FindServersOnNetworkRequestLike, callback: ResponseCallback<ServerOnNetwork[]>): void;
|
|
1137
|
-
public findServersOnNetwork(...args:
|
|
1165
|
+
public findServersOnNetwork(...args: unknown[]): Promise<ServerOnNetwork[]> | undefined {
|
|
1138
1166
|
if (args.length === 1) {
|
|
1139
|
-
|
|
1167
|
+
this.findServersOnNetwork({} as FindServersOnNetworkRequestOptions, args[0] as ResponseCallback<ServerOnNetwork[]>);
|
|
1168
|
+
return undefined;
|
|
1140
1169
|
}
|
|
1141
1170
|
const options = args[0] as FindServersOnNetworkRequestOptions;
|
|
1142
1171
|
const callback = args[1] as ResponseCallback<ServerOnNetwork[]>;
|
|
@@ -1144,21 +1173,24 @@ export class ClientBaseImpl extends OPCUASecureObject implements OPCUAClientBase
|
|
|
1144
1173
|
|
|
1145
1174
|
this.performMessageTransaction(request, (err: Error | null, response?: Response) => {
|
|
1146
1175
|
if (err) {
|
|
1147
|
-
|
|
1176
|
+
callback(err);
|
|
1177
|
+
return;
|
|
1148
1178
|
}
|
|
1149
1179
|
/* c8 ignore next */
|
|
1150
1180
|
if (!response || !(response instanceof FindServersOnNetworkResponse)) {
|
|
1151
|
-
|
|
1181
|
+
callback(new Error("Internal Error"));
|
|
1182
|
+
return;
|
|
1152
1183
|
}
|
|
1153
1184
|
response.servers = response.servers || [];
|
|
1154
1185
|
callback(null, response.servers);
|
|
1155
1186
|
});
|
|
1187
|
+
return undefined;
|
|
1156
1188
|
}
|
|
1157
1189
|
|
|
1158
1190
|
public _removeSession(session: ClientSessionImpl): void {
|
|
1159
1191
|
const index = this._sessions.indexOf(session);
|
|
1160
1192
|
if (index >= 0) {
|
|
1161
|
-
const
|
|
1193
|
+
const _s = this._sessions.splice(index, 1)[0];
|
|
1162
1194
|
// assert(s === session);
|
|
1163
1195
|
// assert(session._client === this);
|
|
1164
1196
|
session._client = null;
|
|
@@ -1183,7 +1215,7 @@ export class ClientBaseImpl extends OPCUASecureObject implements OPCUAClientBase
|
|
|
1183
1215
|
return callback(null);
|
|
1184
1216
|
}
|
|
1185
1217
|
|
|
1186
|
-
debugLog(chalk.bgWhite.green("_closeSession ") + this._secureChannel
|
|
1218
|
+
debugLog(chalk.bgWhite.green("_closeSession ") + this._secureChannel.channelId);
|
|
1187
1219
|
|
|
1188
1220
|
const request = new CloseSessionRequest({
|
|
1189
1221
|
deleteSubscriptions
|
|
@@ -1198,19 +1230,16 @@ export class ClientBaseImpl extends OPCUASecureObject implements OPCUAClientBase
|
|
|
1198
1230
|
});
|
|
1199
1231
|
}
|
|
1200
1232
|
|
|
1201
|
-
public closeSession(
|
|
1202
|
-
|
|
1203
|
-
|
|
1204
|
-
const callback = args[2];
|
|
1205
|
-
|
|
1233
|
+
public closeSession(session: ClientSessionImpl, deleteSubscriptions: boolean): Promise<void>;
|
|
1234
|
+
public closeSession(session: ClientSessionImpl, deleteSubscriptions: boolean, callback: ErrorCallback): void;
|
|
1235
|
+
public closeSession(session: ClientSessionImpl, deleteSubscriptions: boolean, callback?: ErrorCallback): Promise<void> | void {
|
|
1206
1236
|
assert(typeof deleteSubscriptions === "boolean");
|
|
1207
|
-
assert(typeof callback === "function");
|
|
1208
1237
|
assert(session);
|
|
1209
1238
|
assert(session._client === this, "session must be attached to this");
|
|
1210
1239
|
session._closed = true;
|
|
1211
1240
|
|
|
1212
1241
|
// todo : send close session on secure channel
|
|
1213
|
-
this._closeSession(session, deleteSubscriptions, (err?: Error | null,
|
|
1242
|
+
this._closeSession(session, deleteSubscriptions, (err?: Error | null, _response?: CloseSessionResponse) => {
|
|
1214
1243
|
session.emitCloseEvent(StatusCodes.Good);
|
|
1215
1244
|
|
|
1216
1245
|
this._removeSession(session);
|
|
@@ -1219,34 +1248,38 @@ export class ClientBaseImpl extends OPCUASecureObject implements OPCUAClientBase
|
|
|
1219
1248
|
assert(this._sessions.indexOf(session) === -1);
|
|
1220
1249
|
assert(session._closed, "session must indicate it is closed");
|
|
1221
1250
|
|
|
1222
|
-
callback(err ? err : undefined);
|
|
1251
|
+
callback?.(err ? err : undefined);
|
|
1223
1252
|
});
|
|
1224
1253
|
}
|
|
1225
1254
|
|
|
1226
1255
|
public disconnect(): Promise<void>;
|
|
1227
1256
|
public disconnect(callback: ErrorCallback): void;
|
|
1228
1257
|
// eslint-disable-next-line max-statements
|
|
1229
|
-
public disconnect(...args:
|
|
1230
|
-
const callback = args[0];
|
|
1258
|
+
public disconnect(...args: unknown[]): undefined | Promise<void> {
|
|
1259
|
+
const callback = args[0] as ErrorCallback;
|
|
1231
1260
|
assert(typeof callback === "function", "expecting a callback function here");
|
|
1232
1261
|
this._reconnectionIsCanceled = true;
|
|
1233
1262
|
if (this._tmpClient) {
|
|
1234
1263
|
warningLog("disconnecting client while tmpClient exists", this._tmpClient.clientName);
|
|
1235
|
-
this._tmpClient.disconnect((
|
|
1264
|
+
this._tmpClient.disconnect((_err) => {
|
|
1236
1265
|
this._tmpClient = undefined;
|
|
1237
1266
|
// retry disconnect on main client
|
|
1238
1267
|
this.disconnect(callback);
|
|
1239
1268
|
});
|
|
1240
|
-
return;
|
|
1269
|
+
return undefined;
|
|
1241
1270
|
}
|
|
1242
1271
|
if (this._internalState === "disconnected" || this._internalState === "disconnecting") {
|
|
1243
1272
|
if (this._internalState === "disconnecting") {
|
|
1244
|
-
warningLog(
|
|
1273
|
+
warningLog(
|
|
1274
|
+
"[NODE-OPCUA-W26] OPCUAClient#disconnect called while already disconnecting. clientName=",
|
|
1275
|
+
this.clientName
|
|
1276
|
+
);
|
|
1245
1277
|
}
|
|
1246
1278
|
if (!this._reconnectionIsCanceled && this.isReconnecting) {
|
|
1247
1279
|
errorLog("Internal Error : _reconnectionIsCanceled should be true if isReconnecting is true");
|
|
1248
1280
|
}
|
|
1249
|
-
|
|
1281
|
+
callback();
|
|
1282
|
+
return undefined;
|
|
1250
1283
|
}
|
|
1251
1284
|
debugLog("disconnecting client! (will set reconnectionIsCanceled to true");
|
|
1252
1285
|
this._reconnectionIsCanceled = true;
|
|
@@ -1262,7 +1295,7 @@ export class ClientBaseImpl extends OPCUASecureObject implements OPCUAClientBase
|
|
|
1262
1295
|
// sessions cannot be cancelled properly and must be discarded.
|
|
1263
1296
|
this.disconnect(callback);
|
|
1264
1297
|
});
|
|
1265
|
-
return;
|
|
1298
|
+
return undefined;
|
|
1266
1299
|
}
|
|
1267
1300
|
|
|
1268
1301
|
if (this._sessions.length && !this.keepPendingSessionsOnDisconnect) {
|
|
@@ -1272,7 +1305,7 @@ export class ClientBaseImpl extends OPCUASecureObject implements OPCUAClientBase
|
|
|
1272
1305
|
this._close_pending_sessions((/*err*/) => {
|
|
1273
1306
|
this.disconnect(callback);
|
|
1274
1307
|
});
|
|
1275
|
-
return;
|
|
1308
|
+
return undefined;
|
|
1276
1309
|
}
|
|
1277
1310
|
|
|
1278
1311
|
debugLog("Disconnecting !");
|
|
@@ -1302,7 +1335,7 @@ export class ClientBaseImpl extends OPCUASecureObject implements OPCUAClientBase
|
|
|
1302
1335
|
}
|
|
1303
1336
|
|
|
1304
1337
|
if (this._secureChannel) {
|
|
1305
|
-
let tmpChannel:
|
|
1338
|
+
let tmpChannel: ClientSecureChannelLayer | null = this._secureChannel;
|
|
1306
1339
|
this._secureChannel = null;
|
|
1307
1340
|
debugLog("Closing channel");
|
|
1308
1341
|
tmpChannel.close(() => {
|
|
@@ -1317,6 +1350,7 @@ export class ClientBaseImpl extends OPCUASecureObject implements OPCUAClientBase
|
|
|
1317
1350
|
// this.emit("close", null);
|
|
1318
1351
|
callback();
|
|
1319
1352
|
}
|
|
1353
|
+
return undefined;
|
|
1320
1354
|
}
|
|
1321
1355
|
|
|
1322
1356
|
// override me !
|
|
@@ -1326,36 +1360,34 @@ export class ClientBaseImpl extends OPCUASecureObject implements OPCUAClientBase
|
|
|
1326
1360
|
|
|
1327
1361
|
public toString(): string {
|
|
1328
1362
|
let str = "\n";
|
|
1329
|
-
str +=
|
|
1330
|
-
str +=
|
|
1331
|
-
str +=
|
|
1332
|
-
str +=
|
|
1333
|
-
|
|
1334
|
-
|
|
1335
|
-
(this.serverCertificate ? makeSHA1Thumbprint(this.serverCertificate).toString("hex") : "") +
|
|
1336
|
-
"\n";
|
|
1363
|
+
str += ` defaultSecureTokenLifetime.... ${this.defaultSecureTokenLifetime}\n`;
|
|
1364
|
+
str += ` securityMode.................. ${MessageSecurityMode[this.securityMode]}\n`;
|
|
1365
|
+
str += ` securityPolicy................ ${this.securityPolicy.toString()}\n`;
|
|
1366
|
+
str += ` certificate fingerprint....... ${makeCertificateThumbPrint(this.getCertificate())?.toString("hex") || "none"}\n`;
|
|
1367
|
+
|
|
1368
|
+
str += ` server certificate fingerprint ${makeCertificateThumbPrint(this.serverCertificate)?.toString("hex") || "none"}\n`;
|
|
1337
1369
|
// this.serverCertificate = options.serverCertificate || null + "\n";
|
|
1338
|
-
str +=
|
|
1339
|
-
str +=
|
|
1340
|
-
str +=
|
|
1341
|
-
str +=
|
|
1342
|
-
str +=
|
|
1370
|
+
str += ` keepSessionAlive.............. ${this.keepSessionAlive}\n`;
|
|
1371
|
+
str += ` bytesRead..................... ${this.bytesRead}\n`;
|
|
1372
|
+
str += ` bytesWritten.................. ${this.bytesWritten}\n`;
|
|
1373
|
+
str += ` transactionsPerformed......... ${this.transactionsPerformed}\n`;
|
|
1374
|
+
str += ` timedOutRequestCount.......... ${this.timedOutRequestCount}\n`;
|
|
1343
1375
|
str += " connectionStrategy." + "\n";
|
|
1344
|
-
str +=
|
|
1345
|
-
str +=
|
|
1346
|
-
str +=
|
|
1347
|
-
str +=
|
|
1348
|
-
str +=
|
|
1349
|
-
str +=
|
|
1350
|
-
str +=
|
|
1351
|
-
str +=
|
|
1352
|
-
str +=
|
|
1353
|
-
str +=
|
|
1354
|
-
str +=
|
|
1355
|
-
str +=
|
|
1376
|
+
str += ` .maxRetry............... ${this.connectionStrategy.maxRetry}\n`;
|
|
1377
|
+
str += ` .initialDelay........... ${this.connectionStrategy.initialDelay}\n`;
|
|
1378
|
+
str += ` .maxDelay............... ${this.connectionStrategy.maxDelay}\n`;
|
|
1379
|
+
str += ` .randomisationFactor.... ${this.connectionStrategy.randomisationFactor}\n`;
|
|
1380
|
+
str += ` keepSessionAlive.............. ${this.keepSessionAlive}\n`;
|
|
1381
|
+
str += ` applicationName............... ${this.applicationName}\n`;
|
|
1382
|
+
str += ` applicationUri................ ${this._getBuiltApplicationUri()}\n`;
|
|
1383
|
+
str += ` clientName.................... ${this.clientName}\n`;
|
|
1384
|
+
str += ` reconnectOnFailure............ ${this.reconnectOnFailure}\n`;
|
|
1385
|
+
str += ` isReconnecting................ ${this.isReconnecting}\n`;
|
|
1386
|
+
str += ` (internal state).............. ${this._internalState}\n`;
|
|
1387
|
+
str += ` sessions count................ ${this.getSessions().length}\n`;
|
|
1356
1388
|
|
|
1357
1389
|
if (this._secureChannel) {
|
|
1358
|
-
str +=
|
|
1390
|
+
str += `secureChannel:\n${this._secureChannel.toString()}`;
|
|
1359
1391
|
}
|
|
1360
1392
|
return str;
|
|
1361
1393
|
}
|
|
@@ -1365,7 +1397,7 @@ export class ClientBaseImpl extends OPCUASecureObject implements OPCUAClientBase
|
|
|
1365
1397
|
}
|
|
1366
1398
|
|
|
1367
1399
|
public getTransportSettings(): IBasicTransportSettings {
|
|
1368
|
-
return this._secureChannel
|
|
1400
|
+
return this._secureChannel?.getTransportSettings() || ({} as IBasicTransportSettings);
|
|
1369
1401
|
}
|
|
1370
1402
|
|
|
1371
1403
|
protected _addSession(session: ClientSessionImpl): void {
|
|
@@ -1412,15 +1444,17 @@ export class ClientBaseImpl extends OPCUASecureObject implements OPCUAClientBase
|
|
|
1412
1444
|
|
|
1413
1445
|
clientCertificateManager: this.clientCertificateManager
|
|
1414
1446
|
};
|
|
1415
|
-
|
|
1447
|
+
__findEndpoint.call(this, discoveryUrl, params, (err: Error | null, result?: FindEndpointResult) => {
|
|
1416
1448
|
if (err) {
|
|
1417
|
-
|
|
1449
|
+
callback(err);
|
|
1450
|
+
return;
|
|
1418
1451
|
}
|
|
1419
1452
|
|
|
1420
1453
|
// c8 ignore next
|
|
1421
1454
|
if (!result) {
|
|
1422
1455
|
const err1 = new Error("internal error");
|
|
1423
|
-
|
|
1456
|
+
callback(err1);
|
|
1457
|
+
return;
|
|
1424
1458
|
}
|
|
1425
1459
|
|
|
1426
1460
|
const endpoint = result.selectedEndpoint;
|
|
@@ -1432,7 +1466,8 @@ export class ClientBaseImpl extends OPCUASecureObject implements OPCUAClientBase
|
|
|
1432
1466
|
" policy = " +
|
|
1433
1467
|
this.securityPolicy
|
|
1434
1468
|
);
|
|
1435
|
-
|
|
1469
|
+
callback(err1);
|
|
1470
|
+
return;
|
|
1436
1471
|
}
|
|
1437
1472
|
|
|
1438
1473
|
assert(endpoint);
|
|
@@ -1440,20 +1475,20 @@ export class ClientBaseImpl extends OPCUASecureObject implements OPCUAClientBase
|
|
|
1440
1475
|
_verify_serverCertificate(this.clientCertificateManager, endpoint.serverCertificate)
|
|
1441
1476
|
.then(() => {
|
|
1442
1477
|
this.serverCertificate = endpoint.serverCertificate;
|
|
1443
|
-
callback(null, endpoint.endpointUrl
|
|
1478
|
+
callback(null, endpoint.endpointUrl || "");
|
|
1444
1479
|
})
|
|
1445
1480
|
.catch((err1: Error) => {
|
|
1446
1481
|
warningLog("[NODE-OPCUA-W25] client's server certificate verification has failed ", err1.message);
|
|
1447
1482
|
warningLog(" clientCertificateManager.rootDir = ", this.clientCertificateManager.rootDir);
|
|
1448
1483
|
|
|
1449
1484
|
const f = (b: Buffer) =>
|
|
1450
|
-
|
|
1485
|
+
` ${b.toString("base64").replace(/(.{80})/g, "$1\n ")}`;
|
|
1451
1486
|
|
|
1452
1487
|
const chain = split_der(endpoint.serverCertificate);
|
|
1453
1488
|
warningLog(` server certificate contains ${chain.length} elements`);
|
|
1454
1489
|
for (let i = 0; i < chain.length; i++) {
|
|
1455
1490
|
const c = chain[i];
|
|
1456
|
-
warningLog("certificate", i,
|
|
1491
|
+
warningLog("certificate", i, `\n${f(c)}`);
|
|
1457
1492
|
}
|
|
1458
1493
|
if (chain.length > 1) {
|
|
1459
1494
|
warningLog(
|
|
@@ -1466,7 +1501,7 @@ export class ClientBaseImpl extends OPCUASecureObject implements OPCUAClientBase
|
|
|
1466
1501
|
" verify that the server certificate is trusted or that server certificate issuer's certificate is present in the issuer folder"
|
|
1467
1502
|
);
|
|
1468
1503
|
}
|
|
1469
|
-
|
|
1504
|
+
callback(err1);
|
|
1470
1505
|
});
|
|
1471
1506
|
});
|
|
1472
1507
|
}
|
|
@@ -1507,30 +1542,27 @@ export class ClientBaseImpl extends OPCUASecureObject implements OPCUAClientBase
|
|
|
1507
1542
|
|
|
1508
1543
|
private _close_pending_sessions(callback: ErrorCallback) {
|
|
1509
1544
|
const sessions = [...this._sessions];
|
|
1510
|
-
async.map(
|
|
1511
|
-
sessions,
|
|
1512
|
-
(session: ClientSessionImpl, next: () => void) => {
|
|
1513
|
-
assert(session._client === this);
|
|
1514
|
-
|
|
1515
|
-
// note: to prevent next to be call twice
|
|
1516
|
-
let _next_already_call = false;
|
|
1517
|
-
session.close((err?: Error) => {
|
|
1518
|
-
if (_next_already_call) {
|
|
1519
|
-
return;
|
|
1520
|
-
}
|
|
1521
|
-
_next_already_call = true;
|
|
1522
1545
|
|
|
1523
|
-
|
|
1524
|
-
|
|
1525
|
-
|
|
1526
|
-
|
|
1527
|
-
|
|
1528
|
-
|
|
1529
|
-
|
|
1530
|
-
|
|
1546
|
+
const closeAll = async (): Promise<void> => {
|
|
1547
|
+
for (const session of sessions) {
|
|
1548
|
+
assert(session._client === this);
|
|
1549
|
+
await new Promise<void>((resolve) => {
|
|
1550
|
+
let resolved = false;
|
|
1551
|
+
session.close((err?: Error) => {
|
|
1552
|
+
if (resolved) return;
|
|
1553
|
+
resolved = true;
|
|
1554
|
+
if (err) {
|
|
1555
|
+
const msg = session.authenticationToken ? session.authenticationToken.toString() : "";
|
|
1556
|
+
debugLog(` failing to close session ${msg}`);
|
|
1557
|
+
}
|
|
1558
|
+
resolve();
|
|
1559
|
+
});
|
|
1531
1560
|
});
|
|
1532
|
-
}
|
|
1533
|
-
|
|
1561
|
+
}
|
|
1562
|
+
};
|
|
1563
|
+
|
|
1564
|
+
closeAll()
|
|
1565
|
+
.then(() => {
|
|
1534
1566
|
// c8 ignore next
|
|
1535
1567
|
if (this._sessions.length > 0) {
|
|
1536
1568
|
debugLog(
|
|
@@ -1540,9 +1572,9 @@ export class ClientBaseImpl extends OPCUASecureObject implements OPCUAClientBase
|
|
|
1540
1572
|
);
|
|
1541
1573
|
}
|
|
1542
1574
|
assert(this._sessions.length === 0, " failed to disconnect exiting sessions ");
|
|
1543
|
-
callback(
|
|
1544
|
-
}
|
|
1545
|
-
|
|
1575
|
+
callback();
|
|
1576
|
+
})
|
|
1577
|
+
.catch((err) => callback(err));
|
|
1546
1578
|
}
|
|
1547
1579
|
|
|
1548
1580
|
private _install_secure_channel_event_handlers(secureChannel: ClientSecureChannelLayer) {
|
|
@@ -1572,7 +1604,7 @@ export class ClientBaseImpl extends OPCUASecureObject implements OPCUAClientBase
|
|
|
1572
1604
|
* @event send_request
|
|
1573
1605
|
* @param message
|
|
1574
1606
|
*/
|
|
1575
|
-
this.emit("send_request", message);
|
|
1607
|
+
this.emit("send_request", message as unknown as Request);
|
|
1576
1608
|
});
|
|
1577
1609
|
|
|
1578
1610
|
secureChannel.on("receive_response", (message: Response1) => {
|
|
@@ -1581,7 +1613,7 @@ export class ClientBaseImpl extends OPCUASecureObject implements OPCUAClientBase
|
|
|
1581
1613
|
* @event receive_response
|
|
1582
1614
|
* @param message
|
|
1583
1615
|
*/
|
|
1584
|
-
this.emit("receive_response", message);
|
|
1616
|
+
this.emit("receive_response", message as unknown as Response);
|
|
1585
1617
|
});
|
|
1586
1618
|
|
|
1587
1619
|
secureChannel.on("lifetime_75", (token: ChannelSecurityToken) => {
|
|
@@ -1594,7 +1626,7 @@ export class ClientBaseImpl extends OPCUASecureObject implements OPCUAClientBase
|
|
|
1594
1626
|
" is about to expired , it's time to request a new token"
|
|
1595
1627
|
);
|
|
1596
1628
|
// forward message to upper level
|
|
1597
|
-
this.emit("lifetime_75", token
|
|
1629
|
+
this.emit("lifetime_75", token);
|
|
1598
1630
|
});
|
|
1599
1631
|
|
|
1600
1632
|
secureChannel.on("security_token_renewed", (token: ChannelSecurityToken) => {
|
|
@@ -1613,7 +1645,7 @@ export class ClientBaseImpl extends OPCUASecureObject implements OPCUAClientBase
|
|
|
1613
1645
|
/**
|
|
1614
1646
|
* @event connection_lost
|
|
1615
1647
|
*/
|
|
1616
|
-
this.emit("connection_lost"
|
|
1648
|
+
this.emit("connection_lost"); // instead of "close"
|
|
1617
1649
|
}
|
|
1618
1650
|
// this is a normal close operation initiated by us
|
|
1619
1651
|
this.emit("close", err); // instead of "close"
|
|
@@ -1628,7 +1660,7 @@ export class ClientBaseImpl extends OPCUASecureObject implements OPCUAClientBase
|
|
|
1628
1660
|
/**
|
|
1629
1661
|
* @event connection_lost
|
|
1630
1662
|
*/
|
|
1631
|
-
this.emit("connection_lost"
|
|
1663
|
+
this.emit("connection_lost"); // instead of "close"
|
|
1632
1664
|
this._repairConnection();
|
|
1633
1665
|
}
|
|
1634
1666
|
}
|
|
@@ -1640,7 +1672,7 @@ export class ClientBaseImpl extends OPCUASecureObject implements OPCUAClientBase
|
|
|
1640
1672
|
* @event timed_out_request
|
|
1641
1673
|
* @param request
|
|
1642
1674
|
*/
|
|
1643
|
-
this.emit("timed_out_request", request);
|
|
1675
|
+
this.emit("timed_out_request", request as unknown as Request);
|
|
1644
1676
|
});
|
|
1645
1677
|
}
|
|
1646
1678
|
|
|
@@ -1676,7 +1708,12 @@ export class ClientBaseImpl extends OPCUASecureObject implements OPCUAClientBase
|
|
|
1676
1708
|
|
|
1677
1709
|
debugLog("Entering _repairConnection ", this._internalState);
|
|
1678
1710
|
if (this.#insideRepairConnection) {
|
|
1679
|
-
errorLog(
|
|
1711
|
+
errorLog(
|
|
1712
|
+
"_repairConnection already in progress internal state = ",
|
|
1713
|
+
this._internalState,
|
|
1714
|
+
"clientName =",
|
|
1715
|
+
this.clientName
|
|
1716
|
+
);
|
|
1680
1717
|
this.#shouldRepairAgain = true;
|
|
1681
1718
|
return;
|
|
1682
1719
|
}
|
|
@@ -1748,15 +1785,15 @@ export class ClientBaseImpl extends OPCUASecureObject implements OPCUAClientBase
|
|
|
1748
1785
|
* @private
|
|
1749
1786
|
*/
|
|
1750
1787
|
public __createSession_step2(
|
|
1751
|
-
|
|
1752
|
-
|
|
1788
|
+
_session: ClientSessionImpl,
|
|
1789
|
+
_callback: (err: Error | null, session?: ClientSessionImpl) => void
|
|
1753
1790
|
): void {
|
|
1754
1791
|
throw new Error("Please override");
|
|
1755
1792
|
}
|
|
1756
1793
|
public _activateSession(
|
|
1757
|
-
|
|
1758
|
-
|
|
1759
|
-
|
|
1794
|
+
_session: ClientSessionImpl,
|
|
1795
|
+
_userIdentity: UserIdentityInfo,
|
|
1796
|
+
_callback: (err: Error | null, session?: ClientSessionImpl) => void
|
|
1760
1797
|
): void {
|
|
1761
1798
|
throw new Error("Please override");
|
|
1762
1799
|
}
|
|
@@ -1765,27 +1802,28 @@ export class ClientBaseImpl extends OPCUASecureObject implements OPCUAClientBase
|
|
|
1765
1802
|
// tslint:disable-next-line: max-classes-per-file
|
|
1766
1803
|
class TmpClient extends ClientBaseImpl {
|
|
1767
1804
|
constructor(options: OPCUAClientBaseOptions) {
|
|
1768
|
-
options.clientName =
|
|
1805
|
+
options.clientName = `${options.clientName || ""}_TmpClient`;
|
|
1769
1806
|
super(options);
|
|
1770
1807
|
}
|
|
1771
1808
|
|
|
1772
1809
|
async connect(endpoint: string): Promise<void>;
|
|
1773
1810
|
connect(endpoint: string, callback: ErrorCallback): void;
|
|
1774
|
-
connect(endpoint: string, callback?: ErrorCallback):
|
|
1811
|
+
connect(endpoint: string, callback?: ErrorCallback): Promise<void> | void {
|
|
1775
1812
|
debugLog("connecting to TmpClient");
|
|
1776
1813
|
|
|
1777
1814
|
// c8 ignore next
|
|
1778
1815
|
if (this._internalState !== "disconnected") {
|
|
1779
|
-
callback
|
|
1816
|
+
callback?.(new Error(`TmpClient#connect: invalid internal state = ${this._internalState}`));
|
|
1780
1817
|
return;
|
|
1781
1818
|
}
|
|
1782
1819
|
|
|
1783
1820
|
this._setInternalState("connecting");
|
|
1784
1821
|
this._connectStep2(endpoint, (err?: Error) => {
|
|
1785
1822
|
if (this.isUnusable()) {
|
|
1786
|
-
|
|
1823
|
+
this._handleUnrecoverableConnectionFailure(new Error("premature disconnection 4"), callback || (() => { }));
|
|
1824
|
+
return;
|
|
1787
1825
|
}
|
|
1788
|
-
callback
|
|
1826
|
+
callback?.(err);
|
|
1789
1827
|
});
|
|
1790
1828
|
}
|
|
1791
1829
|
}
|
|
@@ -1793,6 +1831,7 @@ class TmpClient extends ClientBaseImpl {
|
|
|
1793
1831
|
// tslint:disable:no-var-requires
|
|
1794
1832
|
// tslint:disable:max-line-length
|
|
1795
1833
|
import { withCallback } from "thenify-ex";
|
|
1834
|
+
|
|
1796
1835
|
ClientBaseImpl.prototype.connect = withCallback(ClientBaseImpl.prototype.connect);
|
|
1797
1836
|
ClientBaseImpl.prototype.disconnect = withCallback(ClientBaseImpl.prototype.disconnect);
|
|
1798
1837
|
ClientBaseImpl.prototype.getEndpoints = withCallback(ClientBaseImpl.prototype.getEndpoints);
|