oracledb 6.0.3 → 6.2.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/README.md +2 -2
- package/build/Release/oracledb-6.2.0-darwin-x64.node +0 -0
- package/build/Release/oracledb-6.2.0-darwin-x64.node-buildinfo.txt +1 -0
- package/build/Release/oracledb-6.2.0-js-buildinfo.txt +1 -0
- package/build/Release/oracledb-6.2.0-linux-arm64.node +0 -0
- package/build/Release/oracledb-6.2.0-linux-arm64.node-buildinfo.txt +1 -0
- package/build/Release/oracledb-6.2.0-linux-x64.node +0 -0
- package/build/Release/oracledb-6.2.0-linux-x64.node-buildinfo.txt +1 -0
- package/build/Release/oracledb-6.2.0-win32-x64.node +0 -0
- package/build/Release/oracledb-6.2.0-win32-x64.node-buildinfo.txt +1 -0
- package/examples/dbconfig.js +7 -14
- package/examples/example.js +0 -1
- package/lib/aqQueue.js +40 -26
- package/lib/connection.js +16 -4
- package/lib/dbObject.js +9 -0
- package/lib/errors.js +17 -13
- package/lib/impl/connection.js +9 -0
- package/lib/impl/resultset.js +7 -4
- package/lib/oracledb.js +26 -18
- package/lib/pool.js +7 -1
- package/lib/sodaCollection.js +12 -1
- package/lib/sodaOperation.js +16 -0
- package/lib/thin/connection.js +229 -182
- package/lib/thin/dbObject.js +4 -1
- package/lib/thin/pool.js +153 -68
- package/lib/thin/protocol/buffer.js +83 -64
- package/lib/thin/protocol/constants.js +3 -14
- package/lib/thin/protocol/encryptDecrypt.js +17 -17
- package/lib/thin/protocol/messages/auth.js +21 -23
- package/lib/thin/protocol/messages/base.js +29 -45
- package/lib/thin/protocol/messages/connectionCookie.js +76 -0
- package/lib/thin/protocol/messages/dataType.js +13 -9
- package/lib/thin/protocol/messages/execute.js +7 -7
- package/lib/thin/protocol/messages/index.js +2 -0
- package/lib/thin/protocol/messages/protocol.js +31 -20
- package/lib/thin/protocol/messages/withData.js +58 -47
- package/lib/thin/protocol/oson.js +17 -14
- package/lib/thin/protocol/packet.js +36 -14
- package/lib/thin/protocol/utils.js +2 -2
- package/lib/thin/resultSet.js +6 -6
- package/lib/thin/sqlnet/connStrategy.js +130 -5
- package/lib/thin/sqlnet/constants.js +2 -0
- package/lib/thin/sqlnet/ezConnectResolver.js +29 -61
- package/lib/thin/sqlnet/navNodes.js +34 -27
- package/lib/thin/sqlnet/networkSession.js +46 -47
- package/lib/thin/sqlnet/ntTcp.js +30 -14
- package/lib/thin/sqlnet/nvStrToNvPair.js +16 -16
- package/lib/thin/sqlnet/packet.js +10 -3
- package/lib/thin/sqlnet/paramParser.js +9 -9
- package/lib/thin/sqlnet/sessionAtts.js +4 -0
- package/lib/thin/statement.js +345 -113
- package/lib/thin/util.js +23 -86
- package/lib/transformer.js +3 -1
- package/lib/util.js +4 -13
- package/lib/version.js +2 -2
- package/package.json +1 -1
- package/build/Release/oracledb-6.0.3-darwin-x64.node +0 -0
- package/build/Release/oracledb-6.0.3-darwin-x64.node-buildinfo.txt +0 -1
- package/build/Release/oracledb-6.0.3-js-buildinfo.txt +0 -1
- package/build/Release/oracledb-6.0.3-linux-arm64.node +0 -0
- package/build/Release/oracledb-6.0.3-linux-arm64.node-buildinfo.txt +0 -1
- package/build/Release/oracledb-6.0.3-linux-x64.node +0 -0
- package/build/Release/oracledb-6.0.3-linux-x64.node-buildinfo.txt +0 -1
- package/build/Release/oracledb-6.0.3-win32-x64.node +0 -0
- package/build/Release/oracledb-6.0.3-win32-x64.node-buildinfo.txt +0 -1
|
@@ -107,6 +107,8 @@ module.exports = {
|
|
|
107
107
|
NSGRAW : 0x1000, // I/O is direct to/from transport
|
|
108
108
|
TNS_VERSION_DESIRED : 319,
|
|
109
109
|
TNS_VERSION_MINIMUM : 300,
|
|
110
|
+
TNS_VERSION_MIN_UUID : 319,
|
|
111
|
+
TNS_UUID_OFFSET : 45,
|
|
110
112
|
|
|
111
113
|
/* Accept Packet */
|
|
112
114
|
NSPACVSN : 8, // connection version
|
|
@@ -26,7 +26,6 @@
|
|
|
26
26
|
|
|
27
27
|
'use strict';
|
|
28
28
|
|
|
29
|
-
const {lookup} = require('dns').promises;
|
|
30
29
|
const errors = require("../../errors.js");
|
|
31
30
|
|
|
32
31
|
// The host information pattern of the EZConnect URL format.
|
|
@@ -71,14 +70,7 @@ const DESCRIPTION_PARAMS = ["ENABLE", "FAILOVER", "LOAD_BALANCE",
|
|
|
71
70
|
class EZConnectResolver {
|
|
72
71
|
constructor(url) {
|
|
73
72
|
this.URL_PROPS_ALIAS = this.initializeUrlAlias();
|
|
74
|
-
|
|
75
|
-
if (jdbcUrlPrefix != -1) {
|
|
76
|
-
this.url = url.substring(jdbcUrlPrefix + 1);
|
|
77
|
-
this.urlPrefix = url.substring(0, jdbcUrlPrefix + 1);
|
|
78
|
-
} else {
|
|
79
|
-
this.url = url;
|
|
80
|
-
this.urlPrefix = "";
|
|
81
|
-
}
|
|
73
|
+
this.url = url;
|
|
82
74
|
this.resolvedUrl = '';
|
|
83
75
|
this.connectionProps = new Map();
|
|
84
76
|
this.urlProps = new Map();
|
|
@@ -89,8 +81,8 @@ class EZConnectResolver {
|
|
|
89
81
|
* Returns the resolved long TNS String.
|
|
90
82
|
* @return Resolved TNS URL.
|
|
91
83
|
*/
|
|
92
|
-
|
|
93
|
-
|
|
84
|
+
getResolvedUrl() {
|
|
85
|
+
this.parse();
|
|
94
86
|
return this.resolvedUrl;
|
|
95
87
|
}
|
|
96
88
|
|
|
@@ -99,33 +91,26 @@ class EZConnectResolver {
|
|
|
99
91
|
* After parsing the extended settings if the remaining part of the URL is in
|
|
100
92
|
* EZConnectURL format then resolve it to long TNS url format.
|
|
101
93
|
*/
|
|
102
|
-
|
|
94
|
+
parse() {
|
|
103
95
|
// First try to parse the extended settings part of the URL.
|
|
104
96
|
let parsedUrl = this.parseExtendedSettings(this.url);
|
|
105
97
|
if (this.connectionProps.size === 0 && this.urlProps.size === 0) {
|
|
106
98
|
// If we have not parsed anything then use the received url as is.
|
|
107
99
|
parsedUrl = this.url;
|
|
108
100
|
}
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
// Skip resolve the URL if it is in TNS format,
|
|
112
|
-
// TNS format starts with '('
|
|
113
|
-
this.resolvedUrl = this.urlPrefix + parsedUrl;
|
|
114
|
-
} else {
|
|
115
|
-
// Try to resolve the EZConnectURL to Long TNS URL.
|
|
116
|
-
this.resolvedUrl = this.urlPrefix + await this.resolveToLongURLFormat(parsedUrl);
|
|
117
|
-
}
|
|
101
|
+
// Try to resolve the EZConnectURL to Long TNS URL.
|
|
102
|
+
this.resolvedUrl = this.resolveToLongURLFormat(parsedUrl);
|
|
118
103
|
}
|
|
119
104
|
/**
|
|
120
105
|
* Translate the given ezconnect url format to Long TNS format.
|
|
121
106
|
* @param url EZConnect URL
|
|
122
107
|
* @return Returns resolved TNS url.
|
|
123
108
|
*/
|
|
124
|
-
|
|
109
|
+
resolveToLongURLFormat(url) {
|
|
125
110
|
// URL is in the following format
|
|
126
111
|
// [protocol://]host1[,host13][:port1][,host2:port2][/service_name][:server][/instance_name]
|
|
127
112
|
|
|
128
|
-
|
|
113
|
+
const urlWithoutWhiteSpaces = url.replace(/\s/g, "");
|
|
129
114
|
let bool = 0;
|
|
130
115
|
let protocol = null, hostInfo = null, serviceName = null, serverMode = null, instanceName = null;
|
|
131
116
|
for (const match of urlWithoutWhiteSpaces.matchAll(EZ_URL_PATTERN)) {
|
|
@@ -151,9 +136,9 @@ class EZConnectResolver {
|
|
|
151
136
|
const proxyHost = this.urlProps.get("HTTPS_PROXY");
|
|
152
137
|
const proxyPort = this.urlProps.get("HTTPS_PROXY_PORT");
|
|
153
138
|
const addressInfo =
|
|
154
|
-
|
|
139
|
+
this.buildAddressList(hostInfo, protocol, proxyHost, proxyPort);
|
|
155
140
|
|
|
156
|
-
|
|
141
|
+
const connectionIdPrefix =
|
|
157
142
|
this.urlProps.get("CONNECTION_ID_PREFIX");
|
|
158
143
|
// Build the available information in TNS format.
|
|
159
144
|
const parts = [];
|
|
@@ -210,11 +195,9 @@ class EZConnectResolver {
|
|
|
210
195
|
* @param proxyPort proxy server port [optional].
|
|
211
196
|
* @return address information of the DESCRIPTION node.
|
|
212
197
|
*/
|
|
213
|
-
|
|
198
|
+
buildAddressList(hostInfo, protocol,
|
|
214
199
|
proxyHost, proxyPort) {
|
|
215
|
-
|
|
216
|
-
let ipcnt = 0;
|
|
217
|
-
let builder = new Array();
|
|
200
|
+
const builder = new Array();
|
|
218
201
|
let proxyInfo = '';
|
|
219
202
|
if (proxyHost != null) {
|
|
220
203
|
if (proxyPort != null) {
|
|
@@ -227,19 +210,18 @@ class EZConnectResolver {
|
|
|
227
210
|
if (protocol == null) protocol = 'TCP';
|
|
228
211
|
let naddr = 0;
|
|
229
212
|
// ; groups the user into a ADDRESS_LIST
|
|
230
|
-
|
|
231
|
-
for (
|
|
213
|
+
const addressLists = hostInfo.split(";");
|
|
214
|
+
for (const addressList in addressLists) {
|
|
232
215
|
let addressNodeCount = 0;
|
|
233
|
-
|
|
216
|
+
const addressListBuilder = new Array();
|
|
234
217
|
for (const match of addressLists[addressList].matchAll(HOSTNAMES_PATTERN)) {
|
|
235
|
-
|
|
218
|
+
const hostnames = (match.groups.hostnames).split(',');
|
|
236
219
|
let port = match.groups.port;
|
|
237
220
|
if (port == null) {
|
|
238
|
-
port = '1521'
|
|
221
|
+
port = '1521'; //default port
|
|
239
222
|
}
|
|
240
|
-
for (
|
|
223
|
+
for (const hname in hostnames) {
|
|
241
224
|
addressListBuilder.push(this.getAddrStr(hostnames[hname], port, protocol, proxyInfo));
|
|
242
|
-
shost = hostnames[hname];
|
|
243
225
|
addressNodeCount++;
|
|
244
226
|
}
|
|
245
227
|
}
|
|
@@ -253,21 +235,6 @@ class EZConnectResolver {
|
|
|
253
235
|
else
|
|
254
236
|
builder.push(parts.join(''));
|
|
255
237
|
}
|
|
256
|
-
if (naddr == 1) {
|
|
257
|
-
shost = shost.trim();
|
|
258
|
-
// If it is IPV6 format address then remove the enclosing '[' and ']'
|
|
259
|
-
if (shost.startsWith("[") && shost.endsWith("]"))
|
|
260
|
-
shost = shost.substring(1, shost.length - 1);
|
|
261
|
-
try {
|
|
262
|
-
await lookup(shost);
|
|
263
|
-
ipcnt++;
|
|
264
|
-
} catch {
|
|
265
|
-
// nothing
|
|
266
|
-
}
|
|
267
|
-
if (ipcnt == 0) {
|
|
268
|
-
errors.throwErr(errors.ERR_INVALID_EZCONNECT_SYNTAX, 'could not resolve hostname', shost);
|
|
269
|
-
}
|
|
270
|
-
}
|
|
271
238
|
|
|
272
239
|
if (addressLists.length < 2 && naddr > 1) {
|
|
273
240
|
this.lb = true;
|
|
@@ -300,7 +267,7 @@ class EZConnectResolver {
|
|
|
300
267
|
buildDescriptionParams() {
|
|
301
268
|
if (this.urlProps.size === 0)
|
|
302
269
|
return '';
|
|
303
|
-
|
|
270
|
+
const builder = new Array();
|
|
304
271
|
this.urlProps.forEach(function(v, k) {
|
|
305
272
|
if (DESCRIPTION_PARAMS.includes(k)) // Add only if it is a DESCRIPTION node parameter
|
|
306
273
|
builder.push(`(${k}=${v})`);
|
|
@@ -318,10 +285,11 @@ class EZConnectResolver {
|
|
|
318
285
|
if (protocol != null && protocol.toLowerCase() == "tcps") {
|
|
319
286
|
// In EZConnect format if the DN match is not specified the enable it
|
|
320
287
|
// by default for TCPS protocol.
|
|
321
|
-
const serverDNMatch = this.urlProps.get("SSL_SERVER_DN_MATCH")
|
|
288
|
+
const serverDNMatch = this.urlProps.get("SSL_SERVER_DN_MATCH");
|
|
322
289
|
const serverCertDN = this.urlProps.get("SSL_SERVER_CERT_DN");
|
|
323
290
|
const walletDir = this.urlProps.get("MY_WALLET_DIRECTORY");
|
|
324
|
-
|
|
291
|
+
if (serverDNMatch != null)
|
|
292
|
+
securityInfo.push(`(SSL_SERVER_DN_MATCH=${serverDNMatch})`);
|
|
325
293
|
if (serverCertDN != null)
|
|
326
294
|
securityInfo.push(`(SSL_SERVER_CERT_DN=${serverCertDN}})`);
|
|
327
295
|
if (walletDir != null)
|
|
@@ -342,8 +310,8 @@ class EZConnectResolver {
|
|
|
342
310
|
* @return the parsed URL which does not contain the extended settings part.
|
|
343
311
|
*/
|
|
344
312
|
parseExtendedSettings(urlStr) {
|
|
345
|
-
|
|
346
|
-
|
|
313
|
+
const urlBytes = Array.from(urlStr.trim());
|
|
314
|
+
const extendedSettingsIndex = this.findExtendedSettingPosition(urlBytes);
|
|
347
315
|
|
|
348
316
|
if (extendedSettingsIndex == -1) {
|
|
349
317
|
return urlStr; // No extended settings configuration found
|
|
@@ -360,7 +328,7 @@ class EZConnectResolver {
|
|
|
360
328
|
parseExtendedProperties(urlChars, extIndex) {
|
|
361
329
|
let key = null;
|
|
362
330
|
let value = null;
|
|
363
|
-
|
|
331
|
+
const token = new Array(urlChars.length);
|
|
364
332
|
let tokenIndx = 0;
|
|
365
333
|
let indices = '';
|
|
366
334
|
for (let i = extIndex; i < urlChars.length; i++) {
|
|
@@ -421,7 +389,7 @@ class EZConnectResolver {
|
|
|
421
389
|
parseQuotedString(startIndex, urlChars, tokenIndex, token) {
|
|
422
390
|
let i = startIndex + 1; // look for closing '"' from the next index
|
|
423
391
|
while (i < urlChars.length) {
|
|
424
|
-
|
|
392
|
+
const curChar = urlChars[i];
|
|
425
393
|
if (curChar == EXT_DOUBLE_QT) {
|
|
426
394
|
// Got the " which ends the quoted block, so break the loop
|
|
427
395
|
// Return the new indices, caller would resume from this new indices.
|
|
@@ -439,8 +407,8 @@ class EZConnectResolver {
|
|
|
439
407
|
* @param value
|
|
440
408
|
*/
|
|
441
409
|
addParam(key, value) {
|
|
442
|
-
|
|
443
|
-
|
|
410
|
+
const aliasKeyName = key.toLowerCase();
|
|
411
|
+
const propertyName = this.URL_PROPS_ALIAS.get(aliasKeyName);
|
|
444
412
|
if (propertyName != null) {
|
|
445
413
|
// if it is an URL alias then add to URL props
|
|
446
414
|
this.urlProps.set(propertyName, value);
|
|
@@ -465,7 +433,7 @@ class EZConnectResolver {
|
|
|
465
433
|
* @return url alias map
|
|
466
434
|
*/
|
|
467
435
|
initializeUrlAlias() {
|
|
468
|
-
|
|
436
|
+
const aliasMap = new Map();
|
|
469
437
|
aliasMap.set("enable", "ENABLE");
|
|
470
438
|
aliasMap.set("failover", "FAILOVER");
|
|
471
439
|
aliasMap.set("load_balance", "LOAD_BALANCE");
|
|
@@ -58,7 +58,7 @@ class Address {
|
|
|
58
58
|
* (ie, "(ADDRESS=(DESCRIPTION=...)) and ")
|
|
59
59
|
*/
|
|
60
60
|
initFromString(s) {
|
|
61
|
-
|
|
61
|
+
const nvp = createNVPair(s);
|
|
62
62
|
this.initFromNVPair(nvp);
|
|
63
63
|
}
|
|
64
64
|
|
|
@@ -70,14 +70,14 @@ class Address {
|
|
|
70
70
|
initFromNVPair(nvp) {
|
|
71
71
|
if (nvp == null || !(nvp.name.toUpperCase() == "ADDRESS"))
|
|
72
72
|
errors.throwErr(errors.ERR_INVALID_CONNECT_STRING_SYNTAX);
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
73
|
+
const protnvp = findNVPairRecurse(nvp, 'protocol');
|
|
74
|
+
const portnvp = findNVPairRecurse(nvp, 'port');
|
|
75
|
+
const hostnvp = findNVPairRecurse(nvp, 'host');
|
|
76
|
+
const httpsProxyNVP = findNVPairRecurse(nvp, 'https_proxy');
|
|
77
|
+
const httpsProxyPortNVP = findNVPairRecurse(nvp, 'https_proxy_port');
|
|
78
78
|
|
|
79
79
|
if (portnvp)
|
|
80
|
-
this.port = portnvp.atom;
|
|
80
|
+
this.port = Number(portnvp.atom);
|
|
81
81
|
|
|
82
82
|
if (hostnvp)
|
|
83
83
|
this.host = hostnvp.atom;
|
|
@@ -88,7 +88,7 @@ class Address {
|
|
|
88
88
|
if (httpsProxyNVP)
|
|
89
89
|
this.httpsProxy = httpsProxyNVP.atom;
|
|
90
90
|
if (httpsProxyPortNVP)
|
|
91
|
-
this.httpsProxyPort = httpsProxyPortNVP.atom;
|
|
91
|
+
this.httpsProxyPort = Number(httpsProxyPortNVP.atom);
|
|
92
92
|
|
|
93
93
|
this.addr = nvp.toString();
|
|
94
94
|
}
|
|
@@ -121,7 +121,7 @@ class AddressList {
|
|
|
121
121
|
* (ie, "(ADDRESS=(DESCRIPTION=...))")
|
|
122
122
|
*/
|
|
123
123
|
initFromString(s) {
|
|
124
|
-
|
|
124
|
+
const nvp = createNVPair(s);
|
|
125
125
|
this.initFromNVPair(nvp);
|
|
126
126
|
}
|
|
127
127
|
|
|
@@ -134,7 +134,7 @@ class AddressList {
|
|
|
134
134
|
/* for each child of "ADDRESS_LIST", create child or set SR/LB/FO */
|
|
135
135
|
this.children = [];
|
|
136
136
|
let childnv, child;
|
|
137
|
-
|
|
137
|
+
const listsize = nvp.getListSize();
|
|
138
138
|
if (listsize == 0) /* atom can not be valid */
|
|
139
139
|
errors.throwErr(errors.ERR_INVALID_CONNECT_STRING_SYNTAX);
|
|
140
140
|
|
|
@@ -216,7 +216,7 @@ class Description {
|
|
|
216
216
|
* Error thrown if invalid syntax (ie, "(ADDRESS=(DESCRIPTION=...))")
|
|
217
217
|
*/
|
|
218
218
|
initFromString(s) {
|
|
219
|
-
|
|
219
|
+
const nvp = createNVPair(s);
|
|
220
220
|
this.initFromNVPair(nvp);
|
|
221
221
|
}
|
|
222
222
|
|
|
@@ -227,7 +227,7 @@ class Description {
|
|
|
227
227
|
*/
|
|
228
228
|
//errors.throwErr(errors.ERR_INVALID_CONNECT_STRING_SYNTAX);
|
|
229
229
|
initFromNVPair(nvp) {
|
|
230
|
-
|
|
230
|
+
const listsize = nvp.getListSize();
|
|
231
231
|
let childnv, child;
|
|
232
232
|
if (listsize == 0) // atom can not be valid
|
|
233
233
|
errors.throwErr(errors.ERR_INVALID_CONNECT_STRING_SYNTAX);
|
|
@@ -256,7 +256,7 @@ class Description {
|
|
|
256
256
|
this.children.push(child);
|
|
257
257
|
} else if (childnv.name.toUpperCase() == "CONNECT_DATA") {
|
|
258
258
|
let tmpnv;
|
|
259
|
-
|
|
259
|
+
const listsize = childnv.getListSize();
|
|
260
260
|
for (let i = 0; i < listsize; i++) {
|
|
261
261
|
tmpnv = childnv.getListElement(i);
|
|
262
262
|
if (tmpnv.name.toUpperCase() == "CONNECTION_ID_PREFIX") {
|
|
@@ -294,7 +294,7 @@ class Description {
|
|
|
294
294
|
if (childnv.atom > 0)
|
|
295
295
|
this.params.expireTime = childnv.atom;
|
|
296
296
|
} else if (childnv.name.toUpperCase() == "SECURITY") {
|
|
297
|
-
|
|
297
|
+
const listsize = childnv.getListSize();
|
|
298
298
|
let tmpnv;
|
|
299
299
|
for (let i = 0; i < listsize; i++) {
|
|
300
300
|
tmpnv = childnv.getListElement(i);
|
|
@@ -304,6 +304,10 @@ class Description {
|
|
|
304
304
|
this.params.sslServerDNMatch = (tmpnv.atom.toLowerCase() == "yes"
|
|
305
305
|
|| tmpnv.atom.toLowerCase() == "on"
|
|
306
306
|
|| tmpnv.atom.toLowerCase() == "true");
|
|
307
|
+
} else if (tmpnv.name.toUpperCase() == "SSL_ALLOW_WEAK_DN_MATCH") {
|
|
308
|
+
this.params.sslAllowWeakDNMatch = (tmpnv.atom.toLowerCase() == "yes"
|
|
309
|
+
|| tmpnv.atom.toLowerCase() == "on"
|
|
310
|
+
|| tmpnv.atom.toLowerCase() == "true");
|
|
307
311
|
} else if ((tmpnv.name.toUpperCase() == "WALLET_LOCATION") || (tmpnv.name.toUpperCase() == "MY_WALLET_DIRECTORY")) {
|
|
308
312
|
this.params.walletLocation = tmpnv.atom;
|
|
309
313
|
}
|
|
@@ -360,7 +364,7 @@ class DescriptionList {
|
|
|
360
364
|
* (ie, "(ADDRESS=(DESCRIPTION=...))")
|
|
361
365
|
*/
|
|
362
366
|
initFromString(s) {
|
|
363
|
-
|
|
367
|
+
const nvp = createNVPair(s);
|
|
364
368
|
this.initFromNVPair(nvp);
|
|
365
369
|
}
|
|
366
370
|
|
|
@@ -370,7 +374,7 @@ class DescriptionList {
|
|
|
370
374
|
* (ie, "(ADDRESS=(DESCRIPTION=...))")
|
|
371
375
|
*/
|
|
372
376
|
initFromNVPair(nvp) {
|
|
373
|
-
|
|
377
|
+
const listsize = nvp.getListSize();
|
|
374
378
|
let child, childnv;
|
|
375
379
|
if (listsize == 0) /* atom can not be valid */
|
|
376
380
|
errors.throwErr(errors.ERR_INVALID_CONNECT_STRING_SYNTAX);
|
|
@@ -482,8 +486,8 @@ class NavAddress extends Address {
|
|
|
482
486
|
if (!net.isIP(this.host)) {
|
|
483
487
|
try {
|
|
484
488
|
addresses = await dnsPromises.lookup(this.host, options);
|
|
485
|
-
for (
|
|
486
|
-
|
|
489
|
+
for (const addr in addresses) {
|
|
490
|
+
const co = new ConnOption();
|
|
487
491
|
co.hostname = this.host;
|
|
488
492
|
co.port = this.port;
|
|
489
493
|
co.protocol = this.prot;
|
|
@@ -503,7 +507,7 @@ class NavAddress extends Address {
|
|
|
503
507
|
// do nothing
|
|
504
508
|
}
|
|
505
509
|
} else {
|
|
506
|
-
|
|
510
|
+
const co = new ConnOption();
|
|
507
511
|
co.hostname = this.host;
|
|
508
512
|
co.port = this.port;
|
|
509
513
|
co.protocol = this.prot;
|
|
@@ -530,7 +534,7 @@ class NavAddress extends Address {
|
|
|
530
534
|
* Address. Constructing a string is mainly needed when source route is ON.
|
|
531
535
|
*/
|
|
532
536
|
addToString(cs) {
|
|
533
|
-
|
|
537
|
+
const NVString = this.toString();
|
|
534
538
|
let cOpts = new Array();
|
|
535
539
|
cOpts = cs.getcurrentDescription().getConnectOptions();
|
|
536
540
|
for (let i = 0;i < cOpts.length; i++) {
|
|
@@ -589,7 +593,7 @@ class NavAddressList extends AddressList {
|
|
|
589
593
|
|
|
590
594
|
}
|
|
591
595
|
addToString(cs) {
|
|
592
|
-
|
|
596
|
+
const NVString = this.toString();
|
|
593
597
|
let cOpts = new Array();
|
|
594
598
|
cOpts = cs.getcurrentDescription().getConnectOptions();
|
|
595
599
|
for (let i = 0;i < cOpts.length; i++) {
|
|
@@ -631,7 +635,7 @@ class NavAddressList extends AddressList {
|
|
|
631
635
|
|
|
632
636
|
closeNVPair(cs) {
|
|
633
637
|
let cOpts = new Array();
|
|
634
|
-
|
|
638
|
+
const childS = this.getChildrenSize();
|
|
635
639
|
if (cs.getcurrentDescription() != null) {
|
|
636
640
|
cOpts = cs.getcurrentDescription().getConnectOptions();
|
|
637
641
|
let numChildren = 0;
|
|
@@ -682,7 +686,7 @@ class NavDescription extends Description {
|
|
|
682
686
|
async navigate(cs) {
|
|
683
687
|
cs.sBuf.length = 0; //reset
|
|
684
688
|
cs.sBuf.push("(DESCRIPTION=");
|
|
685
|
-
|
|
689
|
+
const desc = cs.newConnectionDescription(); //connectiondescription
|
|
686
690
|
if (this.retryCount != null) {
|
|
687
691
|
cs.retryCount = this.getIntValue(this.retryCount, cs.retryCount);
|
|
688
692
|
desc.retryCount = cs.retryCount;
|
|
@@ -711,7 +715,7 @@ class NavDescription extends Description {
|
|
|
711
715
|
if ('enable' in this.params) {
|
|
712
716
|
cs.sBuf.push("(ENABLE=" + this.params.enable + ")");
|
|
713
717
|
}
|
|
714
|
-
if (('sslServerCertDN' in this.params) || ('sslServerDNMatch' in this.params) || ('walletLocation' in this.params)) {
|
|
718
|
+
if (('sslServerCertDN' in this.params) || ('sslServerDNMatch' in this.params) || ('walletLocation' in this.params) || ('sslAllowWeakDNMatch' in this.params)) {
|
|
715
719
|
cs.sBuf.push("(SECURITY=");
|
|
716
720
|
if ('sslServerCertDN' in this.params) {
|
|
717
721
|
cs.sBuf.push("(SSL_SERVER_CERT_DN=" + this.params.sslServerCertDN + ")");
|
|
@@ -719,6 +723,9 @@ class NavDescription extends Description {
|
|
|
719
723
|
if ('sslServerDNMatch' in this.params) {
|
|
720
724
|
cs.sBuf.push("(SSL_SERVER_DN_MATCH=" + this.params.sslServerDNMatch + ")");
|
|
721
725
|
}
|
|
726
|
+
if ('sslAllowWeakDNMatch' in this.params) {
|
|
727
|
+
cs.sBuf.push("(SSL_ALLOW_WEAK_DN_MATCH=" + this.params.sslAllowWeakDNMatch + ")");
|
|
728
|
+
}
|
|
722
729
|
if ('walletLocation' in this.params) {
|
|
723
730
|
cs.sBuf.push("(WALLET_LOCATION=" + this.params.walletLocation + ")");
|
|
724
731
|
}
|
|
@@ -834,10 +841,10 @@ class NavDescriptionList extends DescriptionList {
|
|
|
834
841
|
*/
|
|
835
842
|
static setActiveChildren(children, failover, loadBalance) {
|
|
836
843
|
let randNumber;
|
|
837
|
-
|
|
844
|
+
const listSize = children.length;
|
|
838
845
|
let tmpChildren = new Array();
|
|
839
|
-
|
|
840
|
-
|
|
846
|
+
const rand = Math.floor(Math.random() * 10);
|
|
847
|
+
const arr = new Array(listSize).fill(false);
|
|
841
848
|
|
|
842
849
|
if (failover) {
|
|
843
850
|
if (loadBalance) {
|
|
@@ -37,7 +37,7 @@ const { Buffer } = require('buffer');
|
|
|
37
37
|
const EzConnect = require("./ezConnectResolver.js");
|
|
38
38
|
const { NLParamParser, tnsnamesFilePath } = require("./paramParser.js");
|
|
39
39
|
const process = require('process');
|
|
40
|
-
|
|
40
|
+
const downHostInstance = require("./connStrategy.js").SOLE_INST_DHCACHE;
|
|
41
41
|
/**
|
|
42
42
|
*
|
|
43
43
|
* @param {string} userConfig
|
|
@@ -45,19 +45,20 @@ const process = require('process');
|
|
|
45
45
|
*/
|
|
46
46
|
|
|
47
47
|
async function getConnectionInfo(userConfig) {
|
|
48
|
-
|
|
48
|
+
const connStr = await resolveConnectStr(userConfig.connectString, userConfig.configDir);
|
|
49
49
|
let nvpair;
|
|
50
50
|
if (typeof connStr === 'string')
|
|
51
51
|
nvpair = createNVPair(connStr);
|
|
52
52
|
else
|
|
53
53
|
nvpair = connStr;//Already a NVPair
|
|
54
54
|
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
55
|
+
const serverVal = findValue(nvpair, ["DESCRIPTION", "CONNECT_DATA", "SERVER"]);
|
|
56
|
+
const connClass = findValue(nvpair, ["DESCRIPTION", "CONNECT_DATA", "POOL_CONNECTION_CLASS"]);
|
|
57
|
+
const svcname = findValue(nvpair, ["DESCRIPTION", "CONNECT_DATA", "SERVICE_NAME"]);
|
|
58
|
+
const sid = findValue(nvpair, ["DESCRIPTION", "CONNECT_DATA", "SID"]);
|
|
59
|
+
const poolPurity = findValue(nvpair, ["DESCRIPTION", "CONNECT_DATA", "POOL_PURITY"]);
|
|
59
60
|
|
|
60
|
-
return [serverVal, connClass, svcname, poolPurity ];
|
|
61
|
+
return [serverVal, connClass, svcname, poolPurity, sid ];
|
|
61
62
|
}
|
|
62
63
|
|
|
63
64
|
/**
|
|
@@ -65,38 +66,32 @@ async function getConnectionInfo(userConfig) {
|
|
|
65
66
|
* @param {String} connStr Connect string
|
|
66
67
|
* @returns AddressNode
|
|
67
68
|
*/
|
|
68
|
-
|
|
69
|
+
const nlParamParser = new NLParamParser;
|
|
69
70
|
async function resolveConnectStr(connectString, configDir) {
|
|
70
|
-
|
|
71
|
+
const connStr = connectString.trim();
|
|
71
72
|
let resolvedVal = connStr;
|
|
72
73
|
if ((connStr.indexOf(')') == -1) || (connStr.indexOf('(') != 0)) {
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
resolvedVal
|
|
77
|
-
}
|
|
78
|
-
try
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
resolvedVal = resolvedVal.getListElement(0);
|
|
86
|
-
} catch (err1) {
|
|
87
|
-
if ((connStr.indexOf(':') != -1) || (connStr.indexOf('/') != -1)) {
|
|
88
|
-
throw err;
|
|
89
|
-
} else {
|
|
90
|
-
throw err1;
|
|
91
|
-
}
|
|
92
|
-
}
|
|
74
|
+
if ((connStr.indexOf(':') != -1) || (connStr.indexOf('/') != -1)) {
|
|
75
|
+
const ezcnObj = new EzConnect(connStr);
|
|
76
|
+
resolvedVal = ezcnObj.getResolvedUrl();
|
|
77
|
+
return resolvedVal;
|
|
78
|
+
} else {
|
|
79
|
+
//try tns alias
|
|
80
|
+
const namesFilePath = tnsnamesFilePath(configDir);
|
|
81
|
+
const p = await nlParamParser.initializeNlpa(namesFilePath);
|
|
82
|
+
resolvedVal = p.get(connStr.toUpperCase());
|
|
83
|
+
if (!resolvedVal)
|
|
84
|
+
errors.throwErr(errors.ERR_TNS_ENTRY_NOT_FOUND, connStr, configDir ? configDir + '/tnsnames.ora' : process.env.TNS_ADMIN + '/tnsnames.ora');
|
|
85
|
+
resolvedVal = resolvedVal.getListElement(0);
|
|
93
86
|
}
|
|
87
|
+
|
|
94
88
|
}
|
|
95
89
|
return resolvedVal;
|
|
90
|
+
|
|
96
91
|
}
|
|
97
92
|
|
|
98
93
|
async function resolveAddress(connStr, configDir) {
|
|
99
|
-
|
|
94
|
+
const connstr = await resolveConnectStr(connStr, configDir);
|
|
100
95
|
return createNode(connstr);
|
|
101
96
|
}
|
|
102
97
|
|
|
@@ -140,23 +135,24 @@ class NetworkSession {
|
|
|
140
135
|
|
|
141
136
|
async getAddress(addressNode, userConfig) {
|
|
142
137
|
/* Get the next address */
|
|
143
|
-
|
|
138
|
+
const address = await addressNode.execute(userConfig);
|
|
144
139
|
/* Prepare connection attributes */
|
|
145
|
-
|
|
140
|
+
const uuid = this.sAtts ? this.sAtts.uuid : null;
|
|
146
141
|
this.sAtts = new SessionAtts(uuid);
|
|
147
142
|
this.sAtts.setFrom(userConfig);
|
|
148
143
|
this.sAtts.setFrom(address.desc.params); /* Resolve attributes from Connect String */
|
|
149
144
|
await this.sAtts.prepare(address.protocol);
|
|
150
145
|
|
|
151
146
|
/* Insert Connection ID */
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
147
|
+
const rootNVPair = createNVPair(address.CNdata.join(""));
|
|
148
|
+
const cdataNVPair = findNVPairRecurse(rootNVPair, "CONNECT_DATA");
|
|
149
|
+
const connidStr = `(CONNECTION_ID=${this.sAtts.connectionId})`;
|
|
150
|
+
const childNVPair = createNVPair(connidStr);
|
|
156
151
|
cdataNVPair.addListElement(childNVPair);
|
|
157
152
|
|
|
158
153
|
this.cData = Buffer.from(rootNVPair.toString(), 'ascii');
|
|
159
154
|
this.cDataNVPair = rootNVPair;
|
|
155
|
+
this.sAtts.nt.cDataNVPair = rootNVPair;
|
|
160
156
|
|
|
161
157
|
return (address);
|
|
162
158
|
}
|
|
@@ -210,7 +206,7 @@ class NetworkSession {
|
|
|
210
206
|
|
|
211
207
|
/* Transport connect */
|
|
212
208
|
if (this.sAtts.transportConnectTimeout) {
|
|
213
|
-
|
|
209
|
+
const asyncPromise = this.transportConnect(address);
|
|
214
210
|
await timeout(asyncPromise, this.sAtts.transportConnectTimeout, "transportConnectTimeout", address, this.sAtts.connectionId);
|
|
215
211
|
} else {
|
|
216
212
|
await this.transportConnect(address);
|
|
@@ -230,9 +226,9 @@ class NetworkSession {
|
|
|
230
226
|
await this._recvPacket();
|
|
231
227
|
this.refusePkt.dataBuf = this.rcvDatapkt.buf.subarray(this.rcvDatapkt.offset, this.rcvDatapkt.len).toString();
|
|
232
228
|
}
|
|
233
|
-
|
|
229
|
+
const nvpair = createNVPair(this.refusePkt.dataBuf);
|
|
234
230
|
this.refusePkt = null;
|
|
235
|
-
|
|
231
|
+
const err = findValue(nvpair, ["DESCRIPTION", "ERR"]);
|
|
236
232
|
if (err == "12514") {
|
|
237
233
|
errors.throwErr(errors.ERR_INVALID_SERVICE_NAME, this.getOption(constants.SVCNAME), address.host, address.port, this.sAtts.connectionId);
|
|
238
234
|
} else if (err == "12505") {
|
|
@@ -249,7 +245,7 @@ class NetworkSession {
|
|
|
249
245
|
}
|
|
250
246
|
this._sendConnect(connectPkt);
|
|
251
247
|
} else if (packet.type === constants.NSPTRD) { /* REDIRECT */
|
|
252
|
-
let adrLen, adrStr,
|
|
248
|
+
let adrLen, adrStr, redirConnData;
|
|
253
249
|
|
|
254
250
|
/* Read and connect to Redirect address */
|
|
255
251
|
if (this.redirectPkt.overflow) {
|
|
@@ -266,8 +262,8 @@ class NetworkSession {
|
|
|
266
262
|
redirConnData = this.cData;
|
|
267
263
|
}
|
|
268
264
|
|
|
269
|
-
redirAddressNode = await resolveAddress(adrStr);
|
|
270
|
-
|
|
265
|
+
const redirAddressNode = await resolveAddress(adrStr);
|
|
266
|
+
const host = address.hostname;
|
|
271
267
|
address = await redirAddressNode.execute();
|
|
272
268
|
if (address.desc)
|
|
273
269
|
this.sAtts.setFrom(address.desc.params); /* Add on attributes from redirect connect String */
|
|
@@ -276,7 +272,7 @@ class NetworkSession {
|
|
|
276
272
|
this.ntAdapter.disconnect(constants.NSFIMM);
|
|
277
273
|
|
|
278
274
|
if (this.sAtts.transportConnectTimeout) {
|
|
279
|
-
|
|
275
|
+
const asyncPromise = this.transportConnect(address);
|
|
280
276
|
await timeout(asyncPromise, this.sAtts.transportConnectTimeout, "transportConnectTimeout", address, this.sAtts.connectionId);
|
|
281
277
|
} else {
|
|
282
278
|
await this.transportConnect(address);
|
|
@@ -311,13 +307,14 @@ class NetworkSession {
|
|
|
311
307
|
do {
|
|
312
308
|
try {
|
|
313
309
|
if (this.sAtts.connectTimeout) {
|
|
314
|
-
|
|
310
|
+
const asyncPromise = this.connect2(address);
|
|
315
311
|
connected = await timeout(asyncPromise, this.sAtts.connectTimeout, "connectTimeout", address, this.sAtts.connectionId);
|
|
316
312
|
} else {
|
|
317
313
|
connected = await this.connect2(address);
|
|
318
314
|
}
|
|
319
315
|
} catch (err) {
|
|
320
|
-
if (err.message.startsWith('NJS-510')) {
|
|
316
|
+
if (err.message.startsWith('NJS-510') && !this.ntAdapter.connected) {
|
|
317
|
+
downHostInstance.markDownHost(address.host, Date.now()); // mark the host as down
|
|
321
318
|
this.ntAdapter.connected = true; // Pretend as connected
|
|
322
319
|
}
|
|
323
320
|
if (this.ntAdapter) {
|
|
@@ -356,6 +353,8 @@ class NetworkSession {
|
|
|
356
353
|
break;
|
|
357
354
|
case constants.NSPTAC: /* ACCEPT */
|
|
358
355
|
Packet.AcceptPacket(packet, this.sAtts);
|
|
356
|
+
this.dbUUID = packet.dbUUID;
|
|
357
|
+
packet.dbUUID = null;
|
|
359
358
|
break;
|
|
360
359
|
case constants.NSPTRF: /* REFUSE */
|
|
361
360
|
this.refusePkt = new Packet.RefusePacket(packet);
|
|
@@ -510,8 +509,8 @@ class NetworkSession {
|
|
|
510
509
|
* Establish network connection
|
|
511
510
|
*/
|
|
512
511
|
async connect(userConfig) {
|
|
513
|
-
|
|
514
|
-
|
|
512
|
+
const connStr = userConfig.connectString ? userConfig.connectString : userConfig.connectionString;
|
|
513
|
+
const addressNode = await resolveAddress(connStr, userConfig.configDir);
|
|
515
514
|
let address;
|
|
516
515
|
try {
|
|
517
516
|
address = await this.getAddress(addressNode, userConfig);
|