oracledb 6.0.2 → 6.1.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.
Files changed (67) hide show
  1. package/README.md +15 -17
  2. package/SECURITY.md +1 -1
  3. package/build/Release/oracledb-6.1.0-darwin-x64.node +0 -0
  4. package/build/Release/oracledb-6.1.0-darwin-x64.node-buildinfo.txt +1 -0
  5. package/build/Release/oracledb-6.1.0-js-buildinfo.txt +1 -0
  6. package/build/Release/oracledb-6.1.0-linux-arm64.node +0 -0
  7. package/build/Release/oracledb-6.1.0-linux-arm64.node-buildinfo.txt +1 -0
  8. package/build/Release/oracledb-6.1.0-linux-x64.node +0 -0
  9. package/build/Release/oracledb-6.1.0-linux-x64.node-buildinfo.txt +1 -0
  10. package/build/Release/oracledb-6.1.0-win32-x64.node +0 -0
  11. package/build/Release/oracledb-6.1.0-win32-x64.node-buildinfo.txt +1 -0
  12. package/examples/example.js +0 -1
  13. package/lib/aqQueue.js +40 -26
  14. package/lib/connection.js +15 -3
  15. package/lib/errors.js +15 -10
  16. package/lib/impl/connection.js +9 -0
  17. package/lib/impl/resultset.js +7 -4
  18. package/lib/oracledb.js +15 -12
  19. package/lib/pool.js +11 -2
  20. package/lib/settings.js +1 -1
  21. package/lib/sodaCollection.js +1 -1
  22. package/lib/thin/connection.js +92 -30
  23. package/lib/thin/dbObject.js +2 -2
  24. package/lib/thin/lob.js +2 -2
  25. package/lib/thin/pool.js +153 -71
  26. package/lib/thin/protocol/buffer.js +24 -6
  27. package/lib/thin/protocol/constants.js +8 -18
  28. package/lib/thin/protocol/encryptDecrypt.js +17 -17
  29. package/lib/thin/protocol/messages/auth.js +27 -31
  30. package/lib/thin/protocol/messages/base.js +30 -53
  31. package/lib/thin/protocol/messages/connectionCookie.js +76 -0
  32. package/lib/thin/protocol/messages/dataType.js +13 -9
  33. package/lib/thin/protocol/messages/execute.js +11 -11
  34. package/lib/thin/protocol/messages/index.js +2 -0
  35. package/lib/thin/protocol/messages/lobOp.js +3 -3
  36. package/lib/thin/protocol/messages/protocol.js +31 -20
  37. package/lib/thin/protocol/messages/withData.js +60 -53
  38. package/lib/thin/protocol/oson.js +4 -4
  39. package/lib/thin/protocol/packet.js +51 -28
  40. package/lib/thin/protocol/protocol.js +12 -7
  41. package/lib/thin/protocol/utils.js +2 -2
  42. package/lib/thin/resultSet.js +6 -6
  43. package/lib/thin/sqlnet/connStrategy.js +134 -7
  44. package/lib/thin/sqlnet/constants.js +2 -0
  45. package/lib/thin/sqlnet/ezConnectResolver.js +29 -24
  46. package/lib/thin/sqlnet/navNodes.js +35 -28
  47. package/lib/thin/sqlnet/networkSession.js +45 -40
  48. package/lib/thin/sqlnet/ntTcp.js +70 -35
  49. package/lib/thin/sqlnet/nvStrToNvPair.js +16 -16
  50. package/lib/thin/sqlnet/packet.js +17 -10
  51. package/lib/thin/sqlnet/paramParser.js +9 -9
  52. package/lib/thin/sqlnet/sessionAtts.js +4 -0
  53. package/lib/thin/statement.js +4 -3
  54. package/lib/thin/util.js +28 -8
  55. package/lib/transformer.js +3 -1
  56. package/lib/util.js +0 -13
  57. package/lib/version.js +2 -2
  58. package/package.json +1 -1
  59. package/build/Release/oracledb-6.0.2-darwin-x64.node +0 -0
  60. package/build/Release/oracledb-6.0.2-darwin-x64.node-buildinfo.txt +0 -1
  61. package/build/Release/oracledb-6.0.2-js-buildinfo.txt +0 -1
  62. package/build/Release/oracledb-6.0.2-linux-arm64.node +0 -0
  63. package/build/Release/oracledb-6.0.2-linux-arm64.node-buildinfo.txt +0 -1
  64. package/build/Release/oracledb-6.0.2-linux-x64.node +0 -0
  65. package/build/Release/oracledb-6.0.2-linux-x64.node-buildinfo.txt +0 -1
  66. package/build/Release/oracledb-6.0.2-win32-x64.node +0 -0
  67. package/build/Release/oracledb-6.0.2-win32-x64.node-buildinfo.txt +0 -1
@@ -71,6 +71,7 @@ class Protocol {
71
71
  while (true) { // eslint-disable-line
72
72
  if (this.nsi.isBreak) {
73
73
  await this.resetMessage();
74
+ delete this.readBuf.savedBuffers;
74
75
  await this.readBuf.waitForPackets();
75
76
  }
76
77
  try {
@@ -78,8 +79,10 @@ class Protocol {
78
79
  break;
79
80
  } catch (err) {
80
81
  if (err instanceof utils.OutOfPacketsError) {
81
- await this.readBuf.waitForPackets();
82
- this.readBuf.restorePoint();
82
+ if (!this.nsi.isBreak) {
83
+ await this.readBuf.waitForPackets();
84
+ this.readBuf.restorePoint();
85
+ }
83
86
  continue;
84
87
  }
85
88
  throw (err);
@@ -108,7 +111,7 @@ class Protocol {
108
111
  this.writeBuf.endRequest();
109
112
  }
110
113
 
111
- async _recoverFromError(message) {
114
+ async _recoverFromError(caughtErr, message) {
112
115
  /*
113
116
  * We have NJS error(protocol related) detected during packet write/read
114
117
  * operation. Issue a break and reset to clear channel . We receive the
@@ -121,10 +124,12 @@ class Protocol {
121
124
  await this.readBuf.waitForPackets();
122
125
  message.decode(this.readBuf);
123
126
  } catch (err) { // Recovery failed
124
- // TODO: throw different error indicating that reset failed, probably
125
- // put inside resetMessage()
126
127
  this.nsi.disconnect();
127
- errors.throwErr(errors.ERR_CONNECTION_CLOSED);
128
+ const newErr = errors.getErr(errors.ERR_CONNECTION_CLOSED);
129
+ caughtErr.message = newErr.message +
130
+ "\nError recovery failed: " + err.message +
131
+ "\nOriginal error: " + caughtErr.message;
132
+ throw caughtErr;
128
133
  }
129
134
  }
130
135
 
@@ -150,7 +155,7 @@ class Protocol {
150
155
  } catch (err) {
151
156
  if (!this.connInProgress &&
152
157
  err.code !== errors.ERR_CONNECTION_CLOSED_CODE) {
153
- await this._recoverFromError(message);
158
+ await this._recoverFromError(err, message);
154
159
  }
155
160
  throw err;
156
161
  } finally {
@@ -43,7 +43,7 @@ function _convertBase64(result, value, size, offset) {
43
43
  function encodeRowID(rowID) {
44
44
  let offset = 0;
45
45
  if (rowID.rba !== 0 || rowID.partitionID !== 0 || rowID.blockNum !== 0 || rowID.slotNum != 0) {
46
- let result = Buffer.alloc(constants.TNS_MAX_ROWID_LENGTH);
46
+ const result = Buffer.alloc(constants.TNS_MAX_ROWID_LENGTH);
47
47
  offset = _convertBase64(result, rowID.rba, 6, offset);
48
48
  offset = _convertBase64(result, rowID.partitionID, 3, offset);
49
49
  offset = _convertBase64(result, rowID.blockNum, 6, offset);
@@ -59,7 +59,7 @@ function setObfuscatedValue(value) {
59
59
  const bytes = Buffer.from(value, 'utf8');
60
60
  const len = Buffer.byteLength(value);
61
61
 
62
- let arr = [];
62
+ const arr = [];
63
63
  for (let i = 0; i < len; i++) {
64
64
  arr.push(buf[i] ^ bytes[i]);
65
65
  }
@@ -68,10 +68,10 @@ class ThinResultSetImpl extends ResultSetImpl {
68
68
  // Returns rows fetched to the common layer in array format
69
69
  //---------------------------------------------------------------------------
70
70
  _processRows(numRowsFetched) {
71
- let rows = [];
72
- let bufferRowIndex = this.statement.bufferRowIndex;
71
+ const rows = [];
72
+ const bufferRowIndex = this.statement.bufferRowIndex;
73
73
  for (let row = bufferRowIndex; row < bufferRowIndex + numRowsFetched; row++) {
74
- let rowObj = [];
74
+ const rowObj = [];
75
75
  for (let col = 0; col < this.statement.numQueryVars; col++) {
76
76
  rowObj.push(this.statement.queryVars[col].values[row]);
77
77
  }
@@ -99,13 +99,13 @@ class ThinResultSetImpl extends ResultSetImpl {
99
99
  } else {
100
100
  // We fetch for the required number of row
101
101
  options.fetchArraySize = options.fetchArraySize - (this.statement.bufferRowCount - this.statement.bufferRowIndex);
102
- let prevBufferRowCount = this.statement.bufferRowCount;
102
+ const prevBufferRowCount = this.statement.bufferRowCount;
103
103
  if (this.statement.moreRowsToFetch && options.fetchArraySize > 0) {
104
104
  await this._fetchMoreRows(options);
105
105
  }
106
106
  options.fetchArraySize = numRows || this.options.fetchArraySize;
107
107
  if (prevBufferRowCount === this.statement.bufferRowCount) {
108
- let numRowsFetched = this.statement.bufferRowCount - this.statement.bufferRowIndex;
108
+ const numRowsFetched = this.statement.bufferRowCount - this.statement.bufferRowIndex;
109
109
  this.statement.bufferRowCount = 0;
110
110
  if (numRowsFetched > 0) {
111
111
  return this._processRows(numRowsFetched);
@@ -113,7 +113,7 @@ class ThinResultSetImpl extends ResultSetImpl {
113
113
  return [];
114
114
  }
115
115
  }
116
- let numRowsFetched = this.statement.bufferRowCount - this.statement.bufferRowIndex;
116
+ const numRowsFetched = this.statement.bufferRowCount - this.statement.bufferRowIndex;
117
117
  return this._processRows(numRowsFetched);
118
118
  }
119
119
 
@@ -28,8 +28,7 @@
28
28
 
29
29
  const { NavAddress, NavAddressList, NavDescription, NavDescriptionList } = require("./navNodes.js");
30
30
  const { createNVPair } = require("./nvStrToNvPair.js");
31
-
32
-
31
+ const errors = require("../../errors.js");
33
32
 
34
33
  /**
35
34
  * Class that holds all possible attributes under Description
@@ -55,6 +54,7 @@ class ConnectDescription {
55
54
  class ConnStrategy {
56
55
  constructor() {
57
56
  this.nextOptToTry = 0;
57
+ this.reorderDescriptionList = 0;
58
58
  this.retryCount = 0;
59
59
  this.lastRetryCounter = 0;
60
60
  this.lastRetryConnectDescription = 0;
@@ -96,9 +96,13 @@ class ConnStrategy {
96
96
  this.retryCount = config.retryCount;
97
97
  }
98
98
  }
99
+ if (!this.reorderDescriptionList) {
100
+ this.descriptionList = SOLE_INST_DHCACHE.reorderDescriptionList(this.descriptionList);
101
+ this.reorderDescriptionList = true;
102
+ }
99
103
  /* We try the address list at least once and upto (1 + retryCount) times */
100
104
  for (let d = this.lastRetryConnectDescription; d < this.descriptionList.length; d++) {
101
- let desc = this.descriptionList[d];
105
+ const desc = this.descriptionList[d];
102
106
  let cOpts = new Array();
103
107
  cOpts = desc.getConnectOptions();
104
108
  let delay = desc.delayInMillis;
@@ -109,8 +113,13 @@ class ConnStrategy {
109
113
  }
110
114
  }
111
115
  for (let i = this.lastRetryCounter; i <= this.retryCount; ++i) {
116
+ //Conn options must be reordered only when all options are tried
117
+ // i.e for retry and before the first try.
118
+ if (this.nextOptToTry == 0) {
119
+ cOpts = SOLE_INST_DHCACHE.reorderAddresses(cOpts);
120
+ }
112
121
  while (this.nextOptToTry < cOpts.length) {
113
- let copt = cOpts[this.nextOptToTry];
122
+ const copt = cOpts[this.nextOptToTry];
114
123
  this.lastRetryCounter = i;
115
124
  this.lastRetryConnectDescription = d;
116
125
  this.nextOptToTry++;
@@ -151,7 +160,7 @@ async function createNode(str) {
151
160
  else
152
161
  nvpair = str; //Already a NVPair
153
162
 
154
- let arg = nvpair.name.toUpperCase();
163
+ const arg = nvpair.name.toUpperCase();
155
164
  let navobj = null;
156
165
  switch (arg) {
157
166
  case "ADDRESS":
@@ -166,10 +175,128 @@ async function createNode(str) {
166
175
  case "DESCRIPTION_LIST":
167
176
  navobj = new NavDescriptionList();
168
177
  break;
178
+ default:
179
+ errors.throwErr(errors.ERR_INVALID_CONNECT_STRING_PARAMETERS,
180
+ `unknown top element ${arg}`);
169
181
  }
170
182
  navobj.initFromNVPair(nvpair);
171
- let cs = new ConnStrategy();
183
+ const cs = new ConnStrategy();
172
184
  await navobj.navigate(cs);
173
185
  return cs;
174
186
  }
175
- module.exports = { createNode };
187
+
188
+
189
+ class DownHostsCache {
190
+
191
+ constructor() {
192
+ // Timeout for each item in the cache
193
+ this.DOWN_HOSTS_TIMEOUT = 600;
194
+ // Minimum amount of time between each refresh
195
+ this.MIN_TIME_BETWEEN_REFRESH = 60;
196
+ // DownHostsCache Map
197
+ this.downHostsCacheMap = new Map();
198
+ // Last Refresh Time
199
+ this.lastRefreshTime = 0;
200
+ }
201
+
202
+ /**
203
+ * Add an address to the cache
204
+ *
205
+ * @param connOption
206
+ * address to be cached
207
+ * @return Map with address as key and time of insertion as value
208
+ */
209
+ markDownHost(addr) {
210
+ return this.downHostsCacheMap.set(addr, Date.now());
211
+ }
212
+
213
+ // Remove elements older than DownHostsTimeout
214
+ refreshCache() {
215
+ if (Date.now() - this.MIN_TIME_BETWEEN_REFRESH * 1000 > this.lastRefreshTime) {
216
+ this.downHostsCacheMap.forEach((value, key) => {
217
+ const entryTime = value;
218
+ if (entryTime != null && ((Date.now() - this.DOWN_HOSTS_TIMEOUT * 1000) > entryTime)) {
219
+ this.downHostsCacheMap.delete(key);
220
+ }
221
+ });
222
+ this.lastRefreshTime = Date.now();
223
+ }
224
+ }
225
+
226
+ /**
227
+ * Reorder addresses such that cached elements
228
+ * occur at the end of the array.
229
+ */
230
+ reorderAddresses(cOpts) {
231
+ this.refreshCache();
232
+
233
+ let topIdx = 0, btmIdx = cOpts.length - 1;
234
+
235
+ while (topIdx < btmIdx) {
236
+
237
+ // increment topIdx if the address is not cached
238
+ while (topIdx <= btmIdx
239
+ && !this.isDownHostsCached(cOpts[topIdx]))
240
+ topIdx++;
241
+
242
+ // decrement btmIdx if address is cached
243
+ while (btmIdx >= topIdx
244
+ && this.isDownHostsCached(cOpts[btmIdx]))
245
+ btmIdx--;
246
+
247
+ // swap cached with uncached
248
+ if (topIdx < btmIdx)
249
+ [cOpts[topIdx], cOpts[btmIdx]] = [cOpts[btmIdx], cOpts[topIdx]];
250
+
251
+ }
252
+ return cOpts;
253
+ }
254
+ /**
255
+ * Return if a desc is cached.
256
+ * A desc is cached if all the connection options(addresses)
257
+ * in that description are cached.
258
+ */
259
+ isDownDescCached(desc) {
260
+ const cOpts = desc.getConnectOptions();
261
+ for (let i = 0; i < cOpts.length; i++) {
262
+ if (!this.isDownHostsCached(cOpts[i]))
263
+ return false;
264
+ }
265
+ return true;
266
+ }
267
+ /**
268
+ * Reorder description list such that description with all connection options in downcache
269
+ * is pushed to the end of the description list
270
+ */
271
+ reorderDescriptionList(descs) {
272
+ this.refreshCache();
273
+
274
+ let topIdx = 0, btmIdx = descs.length - 1;
275
+
276
+ while (topIdx < btmIdx) {
277
+
278
+ // increment topIdx if the desc is not cached
279
+ while (topIdx <= btmIdx
280
+ && !this.isDownDescCached(descs[topIdx]))
281
+ topIdx++;
282
+
283
+ // decrement btmIdx if desc is cached
284
+ while (btmIdx >= topIdx
285
+ && this.isDownDescCached(descs[btmIdx]))
286
+ btmIdx--;
287
+
288
+ // swap cached with uncached
289
+ if (topIdx < btmIdx) {
290
+ [descs[topIdx], descs[btmIdx]] = [descs[btmIdx], descs[topIdx]];
291
+ }
292
+ }
293
+ return descs;
294
+ }
295
+ // Return if a host is cached
296
+ isDownHostsCached(copt) {
297
+ return this.downHostsCacheMap.has(copt.host);
298
+ }
299
+ }
300
+ // Single instance
301
+ const SOLE_INST_DHCACHE = new DownHostsCache();
302
+ module.exports = { createNode, SOLE_INST_DHCACHE };
@@ -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
@@ -39,8 +39,7 @@ Test Case in oracle_private/ezconnectTest.js
39
39
  const HOSTNAMES_PATTERN = new RegExp("((?=(?<hostnames>(((\\[[A-z0-9:]+\\])|([A-z0-9][A-z0-9._-]+))[,]?)+)))\\k<hostnames>(:(?<port>\\d+)?)?", 'g');
40
40
 
41
41
  // The EZConnect pattern without the extended settings part.
42
- const EZ_URL_PATTERN = new RegExp("^((?<protocol>tcp|tcps):)?"
43
- + "(//)?"
42
+ const EZ_URL_PATTERN = new RegExp("^(((?<protocol>[A-z0-9]+):)?//)?"
44
43
  + "(?<hostinfo>(" + HOSTNAMES_PATTERN.source + "(?=([,]|[;]|[/]|[:]|$))([,]|[;])?)+)"
45
44
  + "(/(?<servicename>[A-z0-9][A-z0-9,-.]+)?)"
46
45
  + "?(:(?<servermode>dedicated|shared|pooled))"
@@ -72,7 +71,7 @@ const DESCRIPTION_PARAMS = ["ENABLE", "FAILOVER", "LOAD_BALANCE",
72
71
  class EZConnectResolver {
73
72
  constructor(url) {
74
73
  this.URL_PROPS_ALIAS = this.initializeUrlAlias();
75
- let jdbcUrlPrefix = url.indexOf('@');
74
+ const jdbcUrlPrefix = url.indexOf('@');
76
75
  if (jdbcUrlPrefix != -1) {
77
76
  this.url = url.substring(jdbcUrlPrefix + 1);
78
77
  this.urlPrefix = url.substring(0, jdbcUrlPrefix + 1);
@@ -126,7 +125,7 @@ class EZConnectResolver {
126
125
  // URL is in the following format
127
126
  // [protocol://]host1[,host13][:port1][,host2:port2][/service_name][:server][/instance_name]
128
127
 
129
- let urlWithoutWhiteSpaces = url.replace(/\s/g, "");
128
+ const urlWithoutWhiteSpaces = url.replace(/\s/g, "");
130
129
  let bool = 0;
131
130
  let protocol = null, hostInfo = null, serviceName = null, serverMode = null, instanceName = null;
132
131
  for (const match of urlWithoutWhiteSpaces.matchAll(EZ_URL_PATTERN)) {
@@ -145,15 +144,16 @@ class EZConnectResolver {
145
144
  if (protocol == null) {
146
145
  if (!(url.includes("//")))
147
146
  protocol = 'TCP';
147
+ } else if (protocol.toLowerCase() != 'tcp' && protocol.toLowerCase() != 'tcps') {
148
+ errors.throwErr(errors.ERR_INVALID_EZCONNECT_SYNTAX, 'Unsupported protocol in thin mode', protocol);
148
149
  }
149
-
150
150
  // Try to get the proxy information from URL properties
151
151
  const proxyHost = this.urlProps.get("HTTPS_PROXY");
152
152
  const proxyPort = this.urlProps.get("HTTPS_PROXY_PORT");
153
153
  const addressInfo =
154
154
  await this.buildAddressList(hostInfo, protocol, proxyHost, proxyPort);
155
155
 
156
- let connectionIdPrefix =
156
+ const connectionIdPrefix =
157
157
  this.urlProps.get("CONNECTION_ID_PREFIX");
158
158
  // Build the available information in TNS format.
159
159
  const parts = [];
@@ -214,26 +214,30 @@ class EZConnectResolver {
214
214
  proxyHost, proxyPort) {
215
215
  let shost = '';
216
216
  let ipcnt = 0;
217
- let builder = new Array();
217
+ const builder = new Array();
218
218
  let proxyInfo = '';
219
- if (proxyHost != null && proxyPort != null) {
220
- proxyInfo = `(HTTPS_PROXY=${proxyHost})(HTTPS_PROXY_PORT=${proxyPort})`;
219
+ if (proxyHost != null) {
220
+ if (proxyPort != null) {
221
+ proxyInfo = `(HTTPS_PROXY=${proxyHost})(HTTPS_PROXY_PORT=${proxyPort})`;
222
+ } else {
223
+ proxyInfo = `(HTTPS_PROXY=${proxyHost})`;
224
+ }
221
225
  }
222
226
 
223
227
  if (protocol == null) protocol = 'TCP';
224
228
  let naddr = 0;
225
229
  // ; groups the user into a ADDRESS_LIST
226
- let addressLists = hostInfo.split(";");
227
- for (let addressList in addressLists) {
230
+ const addressLists = hostInfo.split(";");
231
+ for (const addressList in addressLists) {
228
232
  let addressNodeCount = 0;
229
- let addressListBuilder = new Array();
233
+ const addressListBuilder = new Array();
230
234
  for (const match of addressLists[addressList].matchAll(HOSTNAMES_PATTERN)) {
231
- let hostnames = (match.groups.hostnames).split(',');
235
+ const hostnames = (match.groups.hostnames).split(',');
232
236
  let port = match.groups.port;
233
237
  if (port == null) {
234
238
  port = '1521' + '';
235
239
  }
236
- for (let hname in hostnames) {
240
+ for (const hname in hostnames) {
237
241
  addressListBuilder.push(this.getAddrStr(hostnames[hname], port, protocol, proxyInfo));
238
242
  shost = hostnames[hname];
239
243
  addressNodeCount++;
@@ -296,7 +300,7 @@ class EZConnectResolver {
296
300
  buildDescriptionParams() {
297
301
  if (this.urlProps.size === 0)
298
302
  return '';
299
- let builder = new Array();
303
+ const builder = new Array();
300
304
  this.urlProps.forEach(function(v, k) {
301
305
  if (DESCRIPTION_PARAMS.includes(k)) // Add only if it is a DESCRIPTION node parameter
302
306
  builder.push(`(${k}=${v})`);
@@ -314,10 +318,11 @@ class EZConnectResolver {
314
318
  if (protocol != null && protocol.toLowerCase() == "tcps") {
315
319
  // In EZConnect format if the DN match is not specified the enable it
316
320
  // by default for TCPS protocol.
317
- const serverDNMatch = this.urlProps.get("SSL_SERVER_DN_MATCH") || 'TRUE';
321
+ const serverDNMatch = this.urlProps.get("SSL_SERVER_DN_MATCH");
318
322
  const serverCertDN = this.urlProps.get("SSL_SERVER_CERT_DN");
319
323
  const walletDir = this.urlProps.get("MY_WALLET_DIRECTORY");
320
- securityInfo.push(`(SSL_SERVER_DN_MATCH=${serverDNMatch})`);
324
+ if (serverDNMatch != null)
325
+ securityInfo.push(`(SSL_SERVER_DN_MATCH=${serverDNMatch})`);
321
326
  if (serverCertDN != null)
322
327
  securityInfo.push(`(SSL_SERVER_CERT_DN=${serverCertDN}})`);
323
328
  if (walletDir != null)
@@ -338,8 +343,8 @@ class EZConnectResolver {
338
343
  * @return the parsed URL which does not contain the extended settings part.
339
344
  */
340
345
  parseExtendedSettings(urlStr) {
341
- let urlBytes = Array.from(urlStr.trim());
342
- let extendedSettingsIndex = this.findExtendedSettingPosition(urlBytes);
346
+ const urlBytes = Array.from(urlStr.trim());
347
+ const extendedSettingsIndex = this.findExtendedSettingPosition(urlBytes);
343
348
 
344
349
  if (extendedSettingsIndex == -1) {
345
350
  return urlStr; // No extended settings configuration found
@@ -356,7 +361,7 @@ class EZConnectResolver {
356
361
  parseExtendedProperties(urlChars, extIndex) {
357
362
  let key = null;
358
363
  let value = null;
359
- let token = new Array(urlChars.length);
364
+ const token = new Array(urlChars.length);
360
365
  let tokenIndx = 0;
361
366
  let indices = '';
362
367
  for (let i = extIndex; i < urlChars.length; i++) {
@@ -417,7 +422,7 @@ class EZConnectResolver {
417
422
  parseQuotedString(startIndex, urlChars, tokenIndex, token) {
418
423
  let i = startIndex + 1; // look for closing '"' from the next index
419
424
  while (i < urlChars.length) {
420
- let curChar = urlChars[i];
425
+ const curChar = urlChars[i];
421
426
  if (curChar == EXT_DOUBLE_QT) {
422
427
  // Got the " which ends the quoted block, so break the loop
423
428
  // Return the new indices, caller would resume from this new indices.
@@ -435,8 +440,8 @@ class EZConnectResolver {
435
440
  * @param value
436
441
  */
437
442
  addParam(key, value) {
438
- let aliasKeyName = key.toLowerCase();
439
- let propertyName = this.URL_PROPS_ALIAS.get(aliasKeyName);
443
+ const aliasKeyName = key.toLowerCase();
444
+ const propertyName = this.URL_PROPS_ALIAS.get(aliasKeyName);
440
445
  if (propertyName != null) {
441
446
  // if it is an URL alias then add to URL props
442
447
  this.urlProps.set(propertyName, value);
@@ -461,7 +466,7 @@ class EZConnectResolver {
461
466
  * @return url alias map
462
467
  */
463
468
  initializeUrlAlias() {
464
- let aliasMap = new Map();
469
+ const aliasMap = new Map();
465
470
  aliasMap.set("enable", "ENABLE");
466
471
  aliasMap.set("failover", "FAILOVER");
467
472
  aliasMap.set("load_balance", "LOAD_BALANCE");
@@ -32,6 +32,7 @@ const os = require("os");
32
32
  const net = require('net');
33
33
  const dns = require('dns');
34
34
  const dnsPromises = dns.promises;
35
+ const cInfo = require("../util.js").CLIENT_INFO;
35
36
 
36
37
  const SchemaObjectFactoryInterface = {
37
38
  ADDR:0,
@@ -57,7 +58,7 @@ class Address {
57
58
  * (ie, "(ADDRESS=(DESCRIPTION=...)) and ")
58
59
  */
59
60
  initFromString(s) {
60
- let nvp = createNVPair(s);
61
+ const nvp = createNVPair(s);
61
62
  this.initFromNVPair(nvp);
62
63
  }
63
64
 
@@ -69,11 +70,11 @@ class Address {
69
70
  initFromNVPair(nvp) {
70
71
  if (nvp == null || !(nvp.name.toUpperCase() == "ADDRESS"))
71
72
  errors.throwErr(errors.ERR_INVALID_CONNECT_STRING_SYNTAX);
72
- let protnvp = findNVPairRecurse(nvp, 'protocol');
73
- let portnvp = findNVPairRecurse(nvp, 'port');
74
- let hostnvp = findNVPairRecurse(nvp, 'host');
75
- let httpsProxyNVP = findNVPairRecurse(nvp, 'https_proxy');
76
- let httpsProxyPortNVP = findNVPairRecurse(nvp, 'https_proxy_port');
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');
77
78
 
78
79
  if (portnvp)
79
80
  this.port = portnvp.atom;
@@ -120,7 +121,7 @@ class AddressList {
120
121
  * (ie, "(ADDRESS=(DESCRIPTION=...))")
121
122
  */
122
123
  initFromString(s) {
123
- let nvp = createNVPair(s);
124
+ const nvp = createNVPair(s);
124
125
  this.initFromNVPair(nvp);
125
126
  }
126
127
 
@@ -133,7 +134,7 @@ class AddressList {
133
134
  /* for each child of "ADDRESS_LIST", create child or set SR/LB/FO */
134
135
  this.children = [];
135
136
  let childnv, child;
136
- let listsize = nvp.getListSize();
137
+ const listsize = nvp.getListSize();
137
138
  if (listsize == 0) /* atom can not be valid */
138
139
  errors.throwErr(errors.ERR_INVALID_CONNECT_STRING_SYNTAX);
139
140
 
@@ -215,7 +216,7 @@ class Description {
215
216
  * Error thrown if invalid syntax (ie, "(ADDRESS=(DESCRIPTION=...))")
216
217
  */
217
218
  initFromString(s) {
218
- let nvp = createNVPair(s);
219
+ const nvp = createNVPair(s);
219
220
  this.initFromNVPair(nvp);
220
221
  }
221
222
 
@@ -226,7 +227,7 @@ class Description {
226
227
  */
227
228
  //errors.throwErr(errors.ERR_INVALID_CONNECT_STRING_SYNTAX);
228
229
  initFromNVPair(nvp) {
229
- let listsize = nvp.getListSize();
230
+ const listsize = nvp.getListSize();
230
231
  let childnv, child;
231
232
  if (listsize == 0) // atom can not be valid
232
233
  errors.throwErr(errors.ERR_INVALID_CONNECT_STRING_SYNTAX);
@@ -255,7 +256,7 @@ class Description {
255
256
  this.children.push(child);
256
257
  } else if (childnv.name.toUpperCase() == "CONNECT_DATA") {
257
258
  let tmpnv;
258
- let listsize = childnv.getListSize();
259
+ const listsize = childnv.getListSize();
259
260
  for (let i = 0; i < listsize; i++) {
260
261
  tmpnv = childnv.getListElement(i);
261
262
  if (tmpnv.name.toUpperCase() == "CONNECTION_ID_PREFIX") {
@@ -293,7 +294,7 @@ class Description {
293
294
  if (childnv.atom > 0)
294
295
  this.params.expireTime = childnv.atom;
295
296
  } else if (childnv.name.toUpperCase() == "SECURITY") {
296
- let listsize = childnv.getListSize();
297
+ const listsize = childnv.getListSize();
297
298
  let tmpnv;
298
299
  for (let i = 0; i < listsize; i++) {
299
300
  tmpnv = childnv.getListElement(i);
@@ -303,6 +304,10 @@ class Description {
303
304
  this.params.sslServerDNMatch = (tmpnv.atom.toLowerCase() == "yes"
304
305
  || tmpnv.atom.toLowerCase() == "on"
305
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");
306
311
  } else if ((tmpnv.name.toUpperCase() == "WALLET_LOCATION") || (tmpnv.name.toUpperCase() == "MY_WALLET_DIRECTORY")) {
307
312
  this.params.walletLocation = tmpnv.atom;
308
313
  }
@@ -359,7 +364,7 @@ class DescriptionList {
359
364
  * (ie, "(ADDRESS=(DESCRIPTION=...))")
360
365
  */
361
366
  initFromString(s) {
362
- let nvp = createNVPair(s);
367
+ const nvp = createNVPair(s);
363
368
  this.initFromNVPair(nvp);
364
369
  }
365
370
 
@@ -369,7 +374,7 @@ class DescriptionList {
369
374
  * (ie, "(ADDRESS=(DESCRIPTION=...))")
370
375
  */
371
376
  initFromNVPair(nvp) {
372
- let listsize = nvp.getListSize();
377
+ const listsize = nvp.getListSize();
373
378
  let child, childnv;
374
379
  if (listsize == 0) /* atom can not be valid */
375
380
  errors.throwErr(errors.ERR_INVALID_CONNECT_STRING_SYNTAX);
@@ -443,7 +448,6 @@ const NavSchemaObject = {
443
448
  LB: "(LOAD_BALANCE=yes)",
444
449
  NFO: "(FAILOVER=false)",
445
450
  CD: "(CONNECT_DATA=",
446
- CID: `(CID=(PROGRAM=nodejs)(HOST=${os.hostname()})(USER=${os.userInfo().username}))`,
447
451
  CONID: "(CONNECTION_ID="
448
452
  };
449
453
  const options = {
@@ -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 (let addr in addresses) {
486
- let co = new ConnOption();
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
- let co = new ConnOption();
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
- let NVString = this.toString();
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
- let NVString = this.toString();
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
- let childS = this.getChildrenSize();
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
- let desc = cs.newConnectionDescription(); //connectiondescription
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
  }
@@ -770,10 +777,10 @@ class NavDescription extends Description {
770
777
  if (this.connectData == null) {
771
778
  this.connectData = "(SERVICE_NAME=)";
772
779
  }
773
-
780
+ const cid = `(CID=(PROGRAM=${cInfo.program})(HOST=${cInfo.hostName})(USER=${cInfo.userName}))`;
774
781
  cOpts[i].CNdata.push(NavSchemaObject.CD);
775
782
  cOpts[i].CNdata.push(this.connectData);
776
- cOpts[i].CNdata.push(NavSchemaObject.CID);
783
+ cOpts[i].CNdata.push(cid);
777
784
  cOpts[i].CNdata.push(")");
778
785
 
779
786
  if (this.SID != null) {
@@ -834,10 +841,10 @@ class NavDescriptionList extends DescriptionList {
834
841
  */
835
842
  static setActiveChildren(children, failover, loadBalance) {
836
843
  let randNumber;
837
- let listSize = children.length;
844
+ const listSize = children.length;
838
845
  let tmpChildren = new Array();
839
- let rand = Math.floor(Math.random() * 10);
840
- let arr = new Array(listSize).fill(false);
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) {