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
@@ -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
- let connStr = await resolveConnectStr(userConfig.connectString, userConfig.configDir);
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
- let serverVal = findValue(nvpair, ["DESCRIPTION", "CONNECT_DATA", "SERVER"]);
56
- let connClass = findValue(nvpair, ["DESCRIPTION", "CONNECT_DATA", "POOL_CONNECTION_CLASS"]);
57
- let svcname = findValue(nvpair, ["DESCRIPTION", "CONNECT_DATA", "SERVICE_NAME"]);
58
- let poolPurity = findValue(nvpair, ["DESCRIPTION", "CONNECT_DATA", "POOL_PURITY"]);
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,20 +66,20 @@ async function getConnectionInfo(userConfig) {
65
66
  * @param {String} connStr Connect string
66
67
  * @returns AddressNode
67
68
  */
68
- let nlParamParser = new NLParamParser;
69
+ const nlParamParser = new NLParamParser;
69
70
  async function resolveConnectStr(connectString, configDir) {
70
- let connStr = connectString.trim();
71
+ const connStr = connectString.trim();
71
72
  let resolvedVal = connStr;
72
73
  if ((connStr.indexOf(')') == -1) || (connStr.indexOf('(') != 0)) {
73
74
  try {
74
75
  /* Try through ezconnect */
75
- let ezcnObj = new EzConnect(connStr);
76
+ const ezcnObj = new EzConnect(connStr);
76
77
  resolvedVal = await ezcnObj.getResolvedUrl();
77
78
  } catch (err) {
78
79
  try {
79
80
  /* try tns alias */
80
- let namesFilePath = tnsnamesFilePath(configDir);
81
- let p = await nlParamParser.initializeNlpa(namesFilePath);
81
+ const namesFilePath = tnsnamesFilePath(configDir);
82
+ const p = await nlParamParser.initializeNlpa(namesFilePath);
82
83
  resolvedVal = p.get(connStr.toUpperCase());
83
84
  if (!resolvedVal)
84
85
  errors.throwErr(errors.ERR_TNS_ENTRY_NOT_FOUND, connStr, configDir ? configDir + '/tnsnames.ora' : process.env.TNS_ADMIN + '/tnsnames.ora');
@@ -96,7 +97,7 @@ async function resolveConnectStr(connectString, configDir) {
96
97
  }
97
98
 
98
99
  async function resolveAddress(connStr, configDir) {
99
- let connstr = await resolveConnectStr(connStr, configDir);
100
+ const connstr = await resolveConnectStr(connStr, configDir);
100
101
  return createNode(connstr);
101
102
  }
102
103
 
@@ -140,23 +141,24 @@ class NetworkSession {
140
141
 
141
142
  async getAddress(addressNode, userConfig) {
142
143
  /* Get the next address */
143
- let address = await addressNode.execute(userConfig);
144
+ const address = await addressNode.execute(userConfig);
144
145
  /* Prepare connection attributes */
145
- let uuid = this.sAtts ? this.sAtts.uuid : null;
146
+ const uuid = this.sAtts ? this.sAtts.uuid : null;
146
147
  this.sAtts = new SessionAtts(uuid);
147
148
  this.sAtts.setFrom(userConfig);
148
149
  this.sAtts.setFrom(address.desc.params); /* Resolve attributes from Connect String */
149
150
  await this.sAtts.prepare(address.protocol);
150
151
 
151
152
  /* Insert Connection ID */
152
- let rootNVPair = createNVPair(address.CNdata.join(""));
153
- let cdataNVPair = findNVPairRecurse(rootNVPair, "CONNECT_DATA");
154
- let connidStr = `(CONNECTION_ID=${this.sAtts.connectionId})`;
155
- let childNVPair = createNVPair(connidStr);
153
+ const rootNVPair = createNVPair(address.CNdata.join(""));
154
+ const cdataNVPair = findNVPairRecurse(rootNVPair, "CONNECT_DATA");
155
+ const connidStr = `(CONNECTION_ID=${this.sAtts.connectionId})`;
156
+ const childNVPair = createNVPair(connidStr);
156
157
  cdataNVPair.addListElement(childNVPair);
157
158
 
158
159
  this.cData = Buffer.from(rootNVPair.toString(), 'ascii');
159
160
  this.cDataNVPair = rootNVPair;
161
+ this.sAtts.nt.cDataNVPair = rootNVPair;
160
162
 
161
163
  return (address);
162
164
  }
@@ -165,6 +167,9 @@ class NetworkSession {
165
167
  * Make the transport level connection
166
168
  */
167
169
  async transportConnect(address) {
170
+ if (address.protocol.toUpperCase() == 'TCP' && address.httpsProxy) {
171
+ errors.throwErr(errors.ERR_INVALID_CONNECT_STRING_PARAMETERS, 'https proxy requires protocol as', 'tcps ');
172
+ }
168
173
  if (address.protocol && (address.protocol.toUpperCase() == 'TCP' || address.protocol.toUpperCase() == 'TCPS')) {
169
174
  this.ntAdapter = new NTTCP(this.sAtts.nt);
170
175
  } else {
@@ -173,8 +178,8 @@ class NetworkSession {
173
178
  await this.ntAdapter.connect(address);
174
179
  this.ntAdapter.startRead();
175
180
  this.sAtts.ntCha = this.ntAdapter.cha;
176
- this.sndDatapkt = new Packet.DataPacket(this.sAtts.sdu, this.sAtts.largeSDU);
177
- this.rcvDatapkt = new Packet.DataPacket(this.sAtts.sdu, this.sAtts.largeSDU);
181
+ this.sndDatapkt = new Packet.DataPacket(this.sAtts.largeSDU);
182
+ this.rcvDatapkt = new Packet.DataPacket(this.sAtts.largeSDU);
178
183
  }
179
184
 
180
185
  /**
@@ -207,7 +212,7 @@ class NetworkSession {
207
212
 
208
213
  /* Transport connect */
209
214
  if (this.sAtts.transportConnectTimeout) {
210
- let asyncPromise = this.transportConnect(address);
215
+ const asyncPromise = this.transportConnect(address);
211
216
  await timeout(asyncPromise, this.sAtts.transportConnectTimeout, "transportConnectTimeout", address, this.sAtts.connectionId);
212
217
  } else {
213
218
  await this.transportConnect(address);
@@ -227,9 +232,9 @@ class NetworkSession {
227
232
  await this._recvPacket();
228
233
  this.refusePkt.dataBuf = this.rcvDatapkt.buf.subarray(this.rcvDatapkt.offset, this.rcvDatapkt.len).toString();
229
234
  }
230
- let nvpair = createNVPair(this.refusePkt.dataBuf);
235
+ const nvpair = createNVPair(this.refusePkt.dataBuf);
231
236
  this.refusePkt = null;
232
- let err = findValue(nvpair, ["DESCRIPTION", "ERR"]);
237
+ const err = findValue(nvpair, ["DESCRIPTION", "ERR"]);
233
238
  if (err == "12514") {
234
239
  errors.throwErr(errors.ERR_INVALID_SERVICE_NAME, this.getOption(constants.SVCNAME), address.host, address.port, this.sAtts.connectionId);
235
240
  } else if (err == "12505") {
@@ -246,7 +251,7 @@ class NetworkSession {
246
251
  }
247
252
  this._sendConnect(connectPkt);
248
253
  } else if (packet.type === constants.NSPTRD) { /* REDIRECT */
249
- let adrLen, adrStr, redirAddressNode, redirConnData;
254
+ let adrLen, adrStr, redirConnData;
250
255
 
251
256
  /* Read and connect to Redirect address */
252
257
  if (this.redirectPkt.overflow) {
@@ -263,8 +268,8 @@ class NetworkSession {
263
268
  redirConnData = this.cData;
264
269
  }
265
270
 
266
- redirAddressNode = await resolveAddress(adrStr);
267
- let host = address.host;
271
+ const redirAddressNode = await resolveAddress(adrStr);
272
+ const host = address.hostname;
268
273
  address = await redirAddressNode.execute();
269
274
  if (address.desc)
270
275
  this.sAtts.setFrom(address.desc.params); /* Add on attributes from redirect connect String */
@@ -273,24 +278,23 @@ class NetworkSession {
273
278
  this.ntAdapter.disconnect(constants.NSFIMM);
274
279
 
275
280
  if (this.sAtts.transportConnectTimeout) {
276
- let asyncPromise = this.transportConnect(address);
281
+ const asyncPromise = this.transportConnect(address);
277
282
  await timeout(asyncPromise, this.sAtts.transportConnectTimeout, "transportConnectTimeout", address, this.sAtts.connectionId);
278
283
  } else {
279
284
  await this.transportConnect(address);
280
285
  }
281
286
 
282
287
  connectPkt = new Packet.ConnectPacket(redirConnData, this.sAtts, constants.NSPFRDR);
288
+ this.sndDatapkt = new Packet.DataPacket(this.sAtts.largeSDU);
283
289
  this._sendConnect(connectPkt);
284
290
  }
285
291
  }
286
292
 
287
293
  /* Accepted */
288
294
  this.connected = true;
289
- this.rcvDatapkt = new Packet.DataPacket(this.sAtts.sdu, this.sAtts.largeSDU);
290
- this.rcvDatapkt.offset = this.rcvDatapkt.dataPtr;
291
- this.rcvDatapkt.len = this.rcvDatapkt.dataPtr;
292
- this.sndDatapkt = new Packet.DataPacket(this.sAtts.sdu, this.sAtts.largeSDU);
293
- this.sndDatapkt.createPacket();
295
+ this.cData = null;
296
+ this.sndDatapkt = new Packet.DataPacket(this.sAtts.largeSDU);
297
+ this.sndDatapkt.createPacket(constants.NSPDADAT); //Currently only used for disconnect
294
298
  this.sndDatapkt.offset = this.sndDatapkt.dataPtr;
295
299
  this.sndDatapkt.len = this.sndDatapkt.bufLen;
296
300
  this.markerPkt = new Packet.MarkerPacket(this.sAtts.largeSDU);
@@ -309,13 +313,14 @@ class NetworkSession {
309
313
  do {
310
314
  try {
311
315
  if (this.sAtts.connectTimeout) {
312
- let asyncPromise = this.connect2(address);
316
+ const asyncPromise = this.connect2(address);
313
317
  connected = await timeout(asyncPromise, this.sAtts.connectTimeout, "connectTimeout", address, this.sAtts.connectionId);
314
318
  } else {
315
319
  connected = await this.connect2(address);
316
320
  }
317
321
  } catch (err) {
318
- if (err.message.startsWith('NJS-510')) {
322
+ if (err.message.startsWith('NJS-510') && !this.ntAdapter.connected) {
323
+ downHostInstance.markDownHost(address.host, Date.now()); // mark the host as down
319
324
  this.ntAdapter.connected = true; // Pretend as connected
320
325
  }
321
326
  if (this.ntAdapter) {
@@ -354,6 +359,8 @@ class NetworkSession {
354
359
  break;
355
360
  case constants.NSPTAC: /* ACCEPT */
356
361
  Packet.AcceptPacket(packet, this.sAtts);
362
+ this.dbUUID = packet.dbUUID;
363
+ packet.dbUUID = null;
357
364
  break;
358
365
  case constants.NSPTRF: /* REFUSE */
359
366
  this.refusePkt = new Packet.RefusePacket(packet);
@@ -466,7 +473,7 @@ class NetworkSession {
466
473
  let bytesCopied = 0;
467
474
 
468
475
  this.sndDatapkt.dataLen = this.sndDatapkt.offset;
469
- if (this.sndDatapkt.dataLen < this.sndDatapkt.bufLen) {
476
+ if (this.sndDatapkt.dataLen < this.sndDatapkt.bufLen || !this.sndDatapkt.bufLen) {
470
477
  bytesCopied = this.sndDatapkt.fillBuf(userBuf, offset, len);
471
478
  len -= bytesCopied;
472
479
  offset += bytesCopied;
@@ -508,8 +515,8 @@ class NetworkSession {
508
515
  * Establish network connection
509
516
  */
510
517
  async connect(userConfig) {
511
- let connStr = userConfig.connectString ? userConfig.connectString : userConfig.connectionString;
512
- let addressNode = await resolveAddress(connStr, userConfig.configDir);
518
+ const connStr = userConfig.connectString ? userConfig.connectString : userConfig.connectionString;
519
+ const addressNode = await resolveAddress(connStr, userConfig.configDir);
513
520
  let address;
514
521
  try {
515
522
  address = await this.getAddress(addressNode, userConfig);
@@ -591,7 +598,6 @@ class NetworkSession {
591
598
  let error = 0;
592
599
  if (this.controlPkt.errno) { /* Control pkt already read */
593
600
  error = this.controlPkt.errno;
594
- this.controlPkt.clear(); /* Clear error */
595
601
  return (error);
596
602
  } else if (!this.getOption(constants.HEALTHCHECK)) {
597
603
  return errors.ERR_CONNECTION_CLOSED;
@@ -602,7 +608,6 @@ class NetworkSession {
602
608
  if (packet.type == constants.NSPTCNL) {
603
609
  this.controlPkt.fromPacket(packet);
604
610
  error = this.controlPkt.errno;
605
- this.controlPkt.clear(); /* Clear error */
606
611
  return (error);
607
612
  } else {
608
613
  this.ntAdapter.packets.unshift(packet); /* Push packet back */
@@ -34,6 +34,7 @@ const http = require("http");
34
34
  const Timers = require('timers');
35
35
  const constants = require("./constants.js");
36
36
  const errors = require("../../errors.js");
37
+ const { findValue } = require("./nvStrToNvPair.js");
37
38
 
38
39
  const PACKET_HEADER_SIZE = 8;
39
40
  const DEFAULT_PORT = 1521;
@@ -47,6 +48,8 @@ const TCPCHA = 1 << 1 | /* ASYNC support */
47
48
  1 << 9 | /* Full Duplex support */
48
49
  1 << 12; /* SIGPIPE Support */
49
50
 
51
+ let streamNum = 1;
52
+
50
53
  /**
51
54
  * Network Transport TCP/TCPS adapter
52
55
  * @param {Address} address Destination Address
@@ -63,28 +66,42 @@ class NTTCP {
63
66
  this.numPacketsSinceLastWait = 0;
64
67
  this.secure = false;
65
68
  this.largeSDU = false;
69
+ this.streamNum = streamNum++;
70
+ this.packetNum = 1;
71
+ this.doDNMatch = true;
66
72
  }
67
73
 
68
74
  /**
69
75
  * DN matching funciton(used with TLS)
70
76
  */
71
77
  dnMatch(serverName, cert) {
72
- if (this.atts.sslServerDNMatch) {
73
- let toObject = str =>str .split(',').map(x => x.split('=').map(y => y.trim())).reduce((a, x) => {
78
+ if (this.atts.sslServerDNMatch && this.doDNMatch) {
79
+ const toObject = str =>str .split(',').map(x => x.split('=').map(y => y.trim())).reduce((a, x) => {
74
80
  a[x[0]] = x[1];
75
81
  return a;
76
82
  }, {});
77
83
  if (this.atts.sslServerCertDN) { /* Full DN Match */
78
- let obj = toObject(this.atts.sslServerCertDN);
79
- for (let key in obj) {
80
- if (obj[key] != cert.subject[key]) {
81
- return (errors.getErr(errors.ERR_TLS_DNMATCH_FAILURE));
84
+ const obj = toObject(this.atts.sslServerCertDN);
85
+ if (Object.keys(obj).length == Object.keys(cert.subject).length) {
86
+ for (const key in obj) {
87
+ if (obj[key] != cert.subject[key]) {
88
+ return (errors.getErr(errors.ERR_TLS_DNMATCH_FAILURE));
89
+ }
82
90
  }
91
+ } else {
92
+ return (errors.getErr(errors.ERR_TLS_DNMATCH_FAILURE));
83
93
  }
84
94
  } else {
85
95
  if (tls.checkServerIdentity(this.hostName, cert) && (!this.originHost || tls.checkServerIdentity(this.originHost, cert))) { /* Hostname match */
86
- const hostName = this.hostName + " " + (this.originHost ? "or " + this.originHost : "");
87
- return (errors.getErr(errors.ERR_TLS_HOSTMATCH_FAILURE, hostName));
96
+ if (this.atts.sslAllowWeakDNMatch) {
97
+ const serviceName = findValue(this.atts.cDataNVPair, ["DESCRIPTION", "CONNECT_DATA", "SERVICE_NAME"]); /* Service Name match */
98
+ if (serviceName != cert.subject.CN) {
99
+ return (errors.getErr(errors.ERR_TLS_DNMATCH_FAILURE));
100
+ }
101
+ } else {
102
+ const hostName = this.hostName + " " + (this.originHost ? "or " + this.originHost : "");
103
+ return (errors.getErr(errors.ERR_TLS_HOSTMATCH_FAILURE, hostName));
104
+ }
88
105
  }
89
106
  }
90
107
  }
@@ -132,7 +149,7 @@ class NTTCP {
132
149
  }
133
150
 
134
151
  let connectErrCause, proxyConnectErrCause, req;
135
- let httpsProxy = address.httpsProxy || this.atts.httpsProxy;
152
+ const httpsProxy = address.httpsProxy || this.atts.httpsProxy;
136
153
  let httpsProxyPort = address.httpsProxyPort || this.atts.httpsProxyPort;
137
154
 
138
155
  await new Promise((resolve) => {
@@ -207,6 +224,8 @@ class NTTCP {
207
224
  if (address.protocol.toUpperCase() == "TCPS") {
208
225
  let secureContext;
209
226
  this.secure = true;
227
+ if (this.atts.sslAllowWeakDNMatch)
228
+ this.doDNMatch = false; //Don't match initial connect
210
229
  try {
211
230
  secureContext = tls.createSecureContext({
212
231
  cert : this.atts.wallet,
@@ -240,7 +259,8 @@ class NTTCP {
240
259
  }
241
260
  this.stream = null;
242
261
  this.connected = false;
243
- this.waiter = null;
262
+ this.drainWaiter = null;
263
+ this.readWaiter = null;
244
264
  }
245
265
 
246
266
  /**
@@ -254,7 +274,7 @@ class NTTCP {
254
274
  const block = buffer.slice(i, i + 8);
255
275
  const hexDumpValues = [];
256
276
  const printableValues = [];
257
- for (let hexByte of block) {
277
+ for (const hexByte of block) {
258
278
  hexDumpValues.push(hexByte.toString(16).toUpperCase().padStart(2, '0'));
259
279
  if (hexByte > 0x20 && hexByte < 0x7f) {
260
280
  printableValues.push(String.fromCharCode(hexByte));
@@ -296,7 +316,7 @@ class NTTCP {
296
316
  */
297
317
  checkErr() {
298
318
  if (!this.connected || this.err) {
299
- let err, newErr;
319
+ let err;
300
320
  if (this.savedErr) {
301
321
  err = errors.getErr(errors.ERR_CONNECTION_LOSTCONTACT,
302
322
  this.host, this.port, this.atts.connectionId, this.savedErr.message);
@@ -304,7 +324,7 @@ class NTTCP {
304
324
  err = errors.getErr(errors.ERR_CONNECTION_EOF, this.host, this.port, this.atts.connectionId,);
305
325
  }
306
326
  /* Wrap around NJS-500 */
307
- newErr = errors.getErr(errors.ERR_CONNECTION_CLOSED);
327
+ const newErr = errors.getErr(errors.ERR_CONNECTION_CLOSED);
308
328
  newErr.message = newErr.message + "\n" + err.message;
309
329
  throw (newErr);
310
330
  }
@@ -318,21 +338,19 @@ class NTTCP {
318
338
  send(buf) {
319
339
  this.checkErr();
320
340
  if (process.env.NODE_ORACLEDB_DEBUG_PACKETS)
321
- this.printPacket("Sending packet", buf);
341
+ this.printPacket(`Sending packet ${this.packetNum} on stream ${this.streamNum}`, buf);
322
342
  const result = this.stream.write(buf, (err) => {
323
343
  if (err) {
324
344
  this.savedErr = err;
325
345
  this.err = true;
326
- if (this.waiter) {
327
- this.waiter();
328
- this.waiter = null;
329
- }
346
+ this._notifyWaiters();
330
347
  }
331
348
  });
332
349
  if (!result) {
333
350
  this.needsDrain = true;
334
351
  }
335
352
  this.numPacketsSinceLastWait++;
353
+ this.packetNum++;
336
354
  }
337
355
 
338
356
  /**
@@ -352,7 +370,9 @@ class NTTCP {
352
370
  async pauseWrite() {
353
371
  this.checkErr();
354
372
  if (this.needsDrain) {
355
- await new Promise((resolve) => this.stream.once('drain', resolve));
373
+ await new Promise((resolve) => {
374
+ this.drainWaiter = resolve;
375
+ });
356
376
  this.checkErr();
357
377
  } else {
358
378
  await new Promise((resolve) => Timers.setImmediate(resolve));
@@ -394,15 +414,16 @@ class NTTCP {
394
414
  const packet = {
395
415
  buf: tempBuf.subarray(0, len),
396
416
  type: tempBuf[4],
397
- flags: tempBuf[5]
417
+ flags: tempBuf[5],
418
+ num : this.packetNum++
398
419
  };
399
420
  this.packets.push(packet);
400
- if (this.waiter) {
401
- this.waiter();
402
- this.waiter = null;
421
+ if (this.readWaiter) {
422
+ this.readWaiter();
423
+ this.readWaiter = null;
403
424
  }
404
425
  if (process.env.NODE_ORACLEDB_DEBUG_PACKETS)
405
- this.printPacket("Receiving packet", packet.buf);
426
+ this.printPacket(`Receiving packet ${packet.num} on stream ${this.streamNum}`, packet.buf);
406
427
 
407
428
  // if the packet consumed all of the bytes (most common scenario), then
408
429
  // simply clear the temporary buffer; otherwise, retain whatever bytes
@@ -436,7 +457,7 @@ class NTTCP {
436
457
  if (this.packets.length === 0) {
437
458
  this.checkErr();
438
459
  await new Promise((resolve) => {
439
- this.waiter = resolve;
460
+ this.readWaiter = resolve;
440
461
  this.numPacketsSinceLastWait = 0;
441
462
  });
442
463
  this.checkErr();
@@ -451,7 +472,8 @@ class NTTCP {
451
472
  async renegTLS() {
452
473
  try {
453
474
  this.checkErr();
454
- let secureContext = tls.createSecureContext({
475
+ this.doDNMatch = true;
476
+ const secureContext = tls.createSecureContext({
455
477
  cert : this.atts.wallet,
456
478
  key : this.atts.wallet,
457
479
  passphrase: this.atts.walletPassword,
@@ -472,26 +494,25 @@ class NTTCP {
472
494
  this.stream.on('error', (err) => {
473
495
  this.savedErr = err;
474
496
  this.err = true;
475
- if (this.waiter) {
476
- this.waiter();
477
- this.waiter = null;
478
- }
497
+ this._notifyWaiters();
479
498
  });
480
499
 
481
500
  this.stream.on('end', () => {
482
501
  this.err = true;
483
- if (this.waiter) {
484
- this.waiter();
485
- this.waiter = null;
486
- }
502
+ this._notifyWaiters();
487
503
  });
488
504
 
489
505
  this.stream.on('close', () => {
490
506
  this.connected = false;
507
+ this._notifyWaiters();
491
508
  });
492
509
 
493
510
  this.stream.on('drain', () => {
494
511
  this.needsDrain = false;
512
+ if (this.drainWaiter) {
513
+ this.drainWaiter();
514
+ this.drainWaiter = null;
515
+ }
495
516
  });
496
517
 
497
518
  }
@@ -508,7 +529,7 @@ class NTTCP {
508
529
  return (this.packets.length > 0);
509
530
  case constants.REMOTEADDR: /* Remote Address */
510
531
  {
511
- let socket = this.secure ? this.connStream : this.stream;
532
+ const socket = this.secure ? this.connStream : this.stream;
512
533
  return (socket.remoteAddress + ":" + socket.remotePort);
513
534
  }
514
535
  default:
@@ -516,6 +537,20 @@ class NTTCP {
516
537
  }
517
538
  }
518
539
 
540
+ /**
541
+ * Notify the waiters (drain and read) and reset them, if applicable.
542
+ */
543
+ _notifyWaiters() {
544
+ if (this.drainWaiter) {
545
+ this.drainWaiter();
546
+ this.drainWaiter = null;
547
+ }
548
+ if (this.readWaiter) {
549
+ this.readWaiter();
550
+ this.readWaiter = null;
551
+ }
552
+ }
553
+
519
554
  }
520
555
 
521
556
  module.exports = NTTCP;
@@ -176,7 +176,7 @@ class NVPair {
176
176
  }
177
177
  } else if (this.listType == LIST_COMMASEP) {
178
178
  for (let i = 0; i < this.getListSize(); i++) {
179
- let listElem = this.getListElement(i);
179
+ const listElem = this.getListElement(i);
180
180
  out = out + listElem.name;
181
181
  if (i != this.getListSize() - 1)
182
182
  out = out + ", ";
@@ -202,7 +202,7 @@ class NVPair {
202
202
  } else if (this.listType == LIST_COMMASEP) {
203
203
  out = out + " (";
204
204
  for (let i = 0; i < this.getListSize(); i++) {
205
- let listElem = this.getListElement(i);
205
+ const listElem = this.getListElement(i);
206
206
  out = out + listElem.name;
207
207
 
208
208
  if (i != this.getListSize() - 1)
@@ -308,7 +308,7 @@ class NVTokens {
308
308
  * function to trim leading and trailing spaces from a literal.
309
309
  */
310
310
  _trimWhiteSpace(it) {
311
- let length = it.length;
311
+ const length = it.length;
312
312
  let start = 0;
313
313
  let end = length;
314
314
 
@@ -337,7 +337,7 @@ class NVTokens {
337
337
  this.tkType = new Array();
338
338
  this.tkValue = new Array();
339
339
 
340
- let len = nvString.length;
340
+ const len = nvString.length;
341
341
  let eql_seen = false;
342
342
  // convert NVString to character array for easier access
343
343
  let input = new Array();
@@ -560,7 +560,7 @@ class NVTokens {
560
560
  * @param nvString the nvString to parse
561
561
  */
562
562
  function createNVPair(nvString) {
563
- let nvt = new NVTokens();
563
+ const nvt = new NVTokens();
564
564
  nvt.parseTokens(nvString);
565
565
  return readTopLevelNVPair(nvt);
566
566
  }
@@ -579,7 +579,7 @@ function readTopLevelNVPair(nvt) {
579
579
  }
580
580
 
581
581
  let name = readNVLiteral(nvt);
582
- let nvp = new NVPair(name);
582
+ const nvp = new NVPair(name);
583
583
 
584
584
  if ((tk = nvt.getToken()) == TKN_COMMA) {
585
585
  // read comma'ed names as one name
@@ -601,14 +601,14 @@ function readTopLevelNVPair(nvt) {
601
601
  */
602
602
  function readNVPair(nvt) {
603
603
  // Opening ( or , for NVPair
604
- let tk = nvt.getToken();
604
+ const tk = nvt.getToken();
605
605
  nvt.eatToken();
606
606
  if (!((tk == TKN_LPAREN) || (tk == TKN_COMMA))) {
607
607
  errors.throwErr(errors.ERR_INVALID_CONNECT_STRING_SYNTAX);
608
608
  }
609
609
 
610
- let name = readNVLiteral(nvt);
611
- let nvp = new NVPair(name);
610
+ const name = readNVLiteral(nvt);
611
+ const nvp = new NVPair(name);
612
612
 
613
613
  return readRightHandSide(nvp, nvt);
614
614
  }
@@ -628,7 +628,7 @@ function readRightHandSide(nvp, nvt) {
628
628
  // otherwise read an NVList.
629
629
  tk = nvt.getToken();
630
630
  if (tk == TKN_LITERAL) {
631
- let value = readNVLiteral(nvt);
631
+ const value = readNVLiteral(nvt);
632
632
  nvp.setAtom = value;
633
633
  } else {
634
634
  // NVList is responsible for adding child NVPairs to this parent
@@ -663,7 +663,7 @@ function readRightHandSide(nvp, nvt) {
663
663
  * function which returns the next literal from NVTokens.
664
664
  */
665
665
  function readNVLiteral(nvt) {
666
- let tk = nvt.getToken();
666
+ const tk = nvt.getToken();
667
667
  if (tk != TKN_LITERAL) {
668
668
  errors.throwErr(errors.ERR_INVALID_CONNECT_STRING_SYNTAX);
669
669
  }
@@ -677,12 +677,12 @@ function readNVLiteral(nvt) {
677
677
  function readNVList(nvt, parent) {
678
678
  // if next token is "(" or ",", then read an NVPair
679
679
  // otherwise, assume epsilon
680
- let tk = nvt.getToken();
680
+ const tk = nvt.getToken();
681
681
  if (!(tk == TKN_LPAREN || tk == TKN_COMMA)) {
682
682
  return; // didn't read an nvpair
683
683
  }
684
684
 
685
- let child = readNVPair(nvt);
685
+ const child = readNVPair(nvt);
686
686
 
687
687
  // read a good NVPair
688
688
  parent.addListElement(child);
@@ -715,7 +715,7 @@ function findNVPairRecurse(nvp, name) {
715
715
 
716
716
  /* Loop thru the list of children and searching each child for name. */
717
717
  for (let i = 0; i < nvp.getListSize(); i++) {
718
- let child = findNVPairRecurse(nvp.getListElement(i), name);
718
+ const child = findNVPairRecurse(nvp.getListElement(i), name);
719
719
 
720
720
  /* Did we find "name"? */
721
721
  if (child !== null)
@@ -742,7 +742,7 @@ function findNVPair(nvp, name) {
742
742
 
743
743
  /* Loop thru the list of children and searching each child for name. */
744
744
  for (let i = 0; i < nvp.getListSize(); i++) {
745
- let child = nvp.getListElement(i);
745
+ const child = nvp.getListElement(i);
746
746
  if (name.toUpperCase() == (child.name).toUpperCase())
747
747
  return child;
748
748
  }
@@ -764,7 +764,7 @@ function findValue(nvp, names) {
764
764
  return null;
765
765
 
766
766
  let output = nvp;
767
- let sze = names.length;
767
+ const sze = names.length;
768
768
 
769
769
  for (let i = 1; i < sze; i++) {
770
770
  output = findNVPair(output, names[i]);