oracledb 6.0.1 → 6.0.3

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 (44) hide show
  1. package/README.md +18 -19
  2. package/SECURITY.md +1 -1
  3. package/build/Release/{oracledb-6.0.1-darwin-x64.node → oracledb-6.0.3-darwin-x64.node} +0 -0
  4. package/build/Release/oracledb-6.0.3-darwin-x64.node-buildinfo.txt +1 -0
  5. package/build/Release/oracledb-6.0.3-js-buildinfo.txt +1 -0
  6. package/build/Release/{oracledb-6.0.1-linux-arm64.node → oracledb-6.0.3-linux-arm64.node} +0 -0
  7. package/build/Release/oracledb-6.0.3-linux-arm64.node-buildinfo.txt +1 -0
  8. package/build/Release/oracledb-6.0.3-linux-x64.node-buildinfo.txt +1 -0
  9. package/build/Release/{oracledb-6.0.1-win32-x64.node → oracledb-6.0.3-win32-x64.node} +0 -0
  10. package/build/Release/oracledb-6.0.3-win32-x64.node-buildinfo.txt +1 -0
  11. package/lib/connection.js +1 -0
  12. package/lib/errors.js +5 -4
  13. package/lib/pool.js +4 -1
  14. package/lib/settings.js +1 -1
  15. package/lib/thin/dbObject.js +17 -5
  16. package/lib/thin/lob.js +2 -2
  17. package/lib/thin/pool.js +10 -12
  18. package/lib/thin/protocol/buffer.js +9 -9
  19. package/lib/thin/protocol/constants.js +5 -4
  20. package/lib/thin/protocol/encryptDecrypt.js +24 -12
  21. package/lib/thin/protocol/messages/auth.js +7 -9
  22. package/lib/thin/protocol/messages/base.js +10 -10
  23. package/lib/thin/protocol/messages/execute.js +5 -5
  24. package/lib/thin/protocol/messages/lobOp.js +3 -3
  25. package/lib/thin/protocol/messages/withData.js +20 -18
  26. package/lib/thin/protocol/packet.js +31 -27
  27. package/lib/thin/protocol/protocol.js +12 -7
  28. package/lib/thin/sqlnet/connStrategy.js +4 -2
  29. package/lib/thin/sqlnet/ezConnectResolver.js +9 -5
  30. package/lib/thin/sqlnet/navNodes.js +3 -3
  31. package/lib/thin/sqlnet/networkSession.js +10 -10
  32. package/lib/thin/sqlnet/ntTcp.js +38 -25
  33. package/lib/thin/sqlnet/packet.js +8 -8
  34. package/lib/thin/sqlnet/paramParser.js +5 -8
  35. package/lib/thin/statement.js +1 -0
  36. package/lib/thin/util.js +21 -0
  37. package/lib/version.js +1 -1
  38. package/package.json +1 -1
  39. package/build/Release/oracledb-6.0.1-darwin-x64.node-buildinfo.txt +0 -1
  40. package/build/Release/oracledb-6.0.1-js-buildinfo.txt +0 -1
  41. package/build/Release/oracledb-6.0.1-linux-arm64.node-buildinfo.txt +0 -1
  42. package/build/Release/oracledb-6.0.1-linux-x64.node-buildinfo.txt +0 -1
  43. package/build/Release/oracledb-6.0.1-win32-x64.node-buildinfo.txt +0 -1
  44. /package/build/Release/{oracledb-6.0.1-linux-x64.node → oracledb-6.0.3-linux-x64.node} +0 -0
@@ -139,7 +139,7 @@ class MessageWithData extends Message {
139
139
 
140
140
  let numBytes = buf.readUB4();
141
141
  if (numBytes > 0) {
142
- buf.skipBytes(numBytes + 1); // current date
142
+ buf.skipBytesChunked(); // current date
143
143
  }
144
144
  buf.skipUB4(); // dcbflag
145
145
  buf.skipUB4(); // dcbmdbz
@@ -147,7 +147,7 @@ class MessageWithData extends Message {
147
147
  buf.skipUB4(); // dcbmxpr
148
148
  numBytes = buf.readUB4();
149
149
  if (numBytes > 0) {
150
- buf.skipBytes(numBytes + 1);
150
+ buf.skipBytesChunked();
151
151
  }
152
152
 
153
153
  this.resultSetsToSetup.push(resultSet);
@@ -173,7 +173,7 @@ class MessageWithData extends Message {
173
173
  let oid;
174
174
  let numBytes = buf.readUB4(); // OID
175
175
  if (numBytes > 0) {
176
- oid = buf.readBytesWithLength();
176
+ oid = Buffer.from(buf.readBytesWithLength());
177
177
  }
178
178
  buf.skipUB2(); // version
179
179
  buf.skipUB2(); // character set id
@@ -190,17 +190,17 @@ class MessageWithData extends Message {
190
190
  let name;
191
191
  numBytes = buf.readUB4();
192
192
  if (numBytes > 0) {
193
- name = buf.readStr(constants.TNS_CS_IMPLICIT);
193
+ name = buf.readStr(constants.CSFRM_IMPLICIT);
194
194
  }
195
195
  let schema;
196
196
  numBytes = buf.readUB4();
197
197
  if (numBytes > 0) {
198
- schema = buf.readStr(constants.TNS_CS_IMPLICIT);
198
+ schema = buf.readStr(constants.CSFRM_IMPLICIT);
199
199
  }
200
200
  numBytes = buf.readUB4();
201
201
  let typeName;
202
202
  if (numBytes > 0) {
203
- typeName = buf.readStr(constants.TNS_CS_IMPLICIT);
203
+ typeName = buf.readStr(constants.CSFRM_IMPLICIT);
204
204
  }
205
205
  buf.skipUB2(); // column position
206
206
  buf.skipUB4(); // uds flag
@@ -316,10 +316,11 @@ class MessageWithData extends Message {
316
316
  processIOVector(buf) {
317
317
  let numBytes;
318
318
  buf.skipUB1(); // flag
319
- const numBinds = buf.readUB2(); // num requests
320
- this.rowIndex = buf.readUB4(); // iter num
319
+ const temp16 = buf.readUB2(); // num requests
320
+ const temp32 = buf.readUB4(); // iter num
321
+ const numBinds = temp32 * 256 + temp16;
321
322
  buf.skipUB4(); // num iters this time
322
- buf.readUB2(); // uac buffer length
323
+ buf.skipUB2(); // uac buffer length
323
324
  numBytes = buf.readUB2(); // bit vector for fast fetch
324
325
  if (numBytes > 0) {
325
326
  buf.skipBytes(numBytes);
@@ -355,7 +356,7 @@ class MessageWithData extends Message {
355
356
  oraTypeNum === constants.TNS_DATA_TYPE_CHAR ||
356
357
  oraTypeNum === constants.TNS_DATA_TYPE_LONG
357
358
  ) {
358
- if (csfrm === constants.TNS_CS_NCHAR) {
359
+ if (csfrm === constants.CSFRM_NCHAR) {
359
360
  buf.caps.checkNCharsetId();
360
361
  }
361
362
  colValue = buf.readStr(csfrm);
@@ -378,9 +379,9 @@ class MessageWithData extends Message {
378
379
  const useLocalTime = (oraTypeNum === constants.TNS_DATA_TYPE_DATE ||
379
380
  oraTypeNum === constants.TNS_DATA_TYPE_TIMESTAMP);
380
381
  colValue = buf.readOracleDate(useLocalTime);
381
- } else if (oraTypeNum === constants.TNS_DATA_TYPE_ROWID) {
382
+ } else if (oraTypeNum === constants.TNS_DATA_TYPE_ROWID) {
382
383
  if (!this.inFetch) {
383
- colValue = buf.readStr(constants.TNS_CS_IMPLICIT);
384
+ colValue = buf.readStr(constants.CSFRM_IMPLICIT);
384
385
  } else {
385
386
  let numBytes = buf.readUInt8();
386
387
  if (isNullLength(numBytes)) {
@@ -392,7 +393,7 @@ class MessageWithData extends Message {
392
393
  }
393
394
  } else if (oraTypeNum === constants.TNS_DATA_TYPE_UROWID) {
394
395
  if (!this.inFetch) {
395
- colValue = buf.readStr(constants.TNS_CS_IMPLICIT);
396
+ colValue = buf.readStr(constants.CSFRM_IMPLICIT);
396
397
  } else {
397
398
  colValue = buf.readURowID();
398
399
  }
@@ -478,7 +479,7 @@ class MessageWithData extends Message {
478
479
  for (let i = 0; i < numParams; i++) {
479
480
  numBytes = buf.readUB2(); // key
480
481
  if (numBytes > 0) {
481
- keyTextValue = buf.readStr(constants.TNS_CS_IMPLICIT);
482
+ keyTextValue = buf.readStr(constants.CSFRM_IMPLICIT);
482
483
  }
483
484
  numBytes = buf.readUB2(); // value
484
485
  if (numBytes > 0) {
@@ -546,6 +547,7 @@ class MessageWithData extends Message {
546
547
  variable.maxSize = constants.TNS_MAX_LONG_LENGTH;
547
548
  }
548
549
  resultSet.statement.requiresDefine = true;
550
+ resultSet.statement.noPrefetch = true;
549
551
  }
550
552
  }
551
553
  }
@@ -563,7 +565,7 @@ class MessageWithData extends Message {
563
565
 
564
566
  if (this.statement.isQuery) {
565
567
  this.inFetch = true;
566
- if (this.statement.queryVars) {
568
+ if (this.statement.queryVars) {
567
569
  this.outVariables = [];
568
570
  for (let i = 0; i < this.statement.queryVars.length; i++) {
569
571
  this.outVariables.push(this.statement.queryVars[i]);
@@ -582,7 +584,7 @@ class MessageWithData extends Message {
582
584
  }
583
585
 
584
586
  getBitVector(buf, numBytes) {
585
- this.bitVector = buf.readBytes(numBytes);
587
+ this.bitVector = Buffer.from(buf.readBytes(numBytes));
586
588
  }
587
589
 
588
590
  processBindParams(buf, params) {
@@ -607,7 +609,7 @@ class MessageWithData extends Message {
607
609
  // NCHAR, NVARCHAR reports ORA-01460: unimplemented or unreasonable
608
610
  // conversion requested if maxSize is not multiplied by the
609
611
  // bufferSizeFactor
610
- if (variable.type._csfrm === constants.TNS_CS_NCHAR) {
612
+ if (variable.type._csfrm === constants.CSFRM_NCHAR) {
611
613
  maxSize *= variable.type._bufferSizeFactor;
612
614
  }
613
615
  if ([constants.TNS_DATA_TYPE_ROWID, constants.TNS_DATA_TYPE_UROWID].includes(oraTypeNum)) {
@@ -731,7 +733,7 @@ class MessageWithData extends Message {
731
733
  oraTypeNum === constants.TNS_DATA_TYPE_LONG ||
732
734
  oraTypeNum === constants.TNS_DATA_TYPE_RAW ||
733
735
  oraTypeNum === constants.TNS_DATA_TYPE_LONG_RAW) {
734
- if (variable.type._csfrm === constants.TNS_CS_NCHAR) {
736
+ if (variable.type._csfrm === constants.CSFRM_NCHAR) {
735
737
  buf.caps.checkNCharsetId();
736
738
  value = Buffer.from(value, constants.TNS_ENCODING_UTF16).swap16();
737
739
  } else {
@@ -220,12 +220,17 @@ class ReadPacket extends BaseBuffer {
220
220
  }
221
221
 
222
222
  // the requested bytes are split across multiple packets; if a chunked read
223
- // is not in progress one is implicitly started; copy the bytes from the
224
- // end of this packet
225
- if (!inChunkedRead) {
226
- this.chunkedBytesBuf.startChunkedRead();
223
+ // is in progress, a chunk is acquired that will accommodate the requested
224
+ // bytes; otherwise, a separate buffer will be allocated to accommodate the
225
+ // requested bytes
226
+ let buf;
227
+ if (inChunkedRead) {
228
+ buf = this.chunkedBytesBuf.getBuf(numBytes);
229
+ } else {
230
+ buf = Buffer.alloc(numBytes);
227
231
  }
228
- const buf = this.chunkedBytesBuf.getBuf(numBytes);
232
+
233
+ // copy the bytes to the buffer from the remainder of this packet
229
234
  let offset = 0;
230
235
  this.buf.copy(buf, offset, this.pos, this.pos + numBytesLeft);
231
236
  offset += numBytesLeft;
@@ -241,10 +246,7 @@ class ReadPacket extends BaseBuffer {
241
246
  numBytes -= numSplitBytes;
242
247
  }
243
248
 
244
- // if not in a chunked bytes read, return the buffer directly
245
- if (!inChunkedRead) {
246
- return this.chunkedBytesBuf.endChunkedRead();
247
- }
249
+ return buf;
248
250
 
249
251
  }
250
252
 
@@ -252,46 +254,48 @@ class ReadPacket extends BaseBuffer {
252
254
  * Receives a packet from the adapter.
253
255
  */
254
256
  receivePacket() {
255
- if (this.savedBufferPos === this.savedBuffers.length) {
257
+ if (this.savedPacketPos === this.savedPackets.length) {
256
258
  const packet = this.nsi.syncRecvPacket();
257
- if (!packet)
259
+ if (!packet || this.nsi.isBreak)
258
260
  throw new utils.OutOfPacketsError();
259
- this.savedBuffers.push(packet.buf);
261
+ this.savedPackets.push(packet);
260
262
  }
261
- this.startPacket(this.savedBuffers[this.savedBufferPos++]);
263
+ this.startPacket(this.savedPackets[this.savedPacketPos++]);
262
264
  }
263
265
 
264
266
  restorePoint() {
265
- this.savedBufferPos = 0;
266
- this.startPacket(this.savedBuffers[this.savedBufferPos++]);
267
+ this.savedPacketPos = 0;
268
+ this.startPacket(this.savedPackets[this.savedPacketPos++]);
267
269
  this.pos = this.savedPos;
268
270
  }
269
271
 
270
272
  savePoint() {
271
- if (this.savedBuffers) {
272
- this.savedBuffers = this.savedBuffers.splice(this.savedBufferPos - 1);
273
+ if (this.savedPackets) {
274
+ this.savedPackets = this.savedPackets.splice(this.savedPacketPos - 1);
273
275
  } else {
274
- this.savedBuffers = [this.buf];
276
+ this.savedPackets = [this.packet];
275
277
  }
276
- this.savedBufferPos = 1;
278
+ this.savedPacketPos = 1;
277
279
  this.savedPos = this.pos;
278
280
  }
279
281
 
280
- startPacket(buf) {
281
- this.buf = buf;
282
+ startPacket(packet) {
283
+ this.packet = packet;
284
+ this.buf = packet.buf;
282
285
  this.pos = 10; // skip packet heaader and data flags
283
- this.size = buf.length;
286
+ this.size = packet.buf.length;
287
+ this.packetNum = packet.num;
284
288
  }
285
289
 
286
290
  async waitForPackets() {
287
291
  const packet = await this.nsi.recvPacket();
288
- if (!this.savedBuffers) {
289
- this.savedBuffers = [packet.buf];
290
- this.savedBufferPos = 0;
292
+ if (!this.savedPackets) {
293
+ this.savedPackets = [packet];
294
+ this.savedPacketPos = 0;
291
295
  } else {
292
- this.savedBuffers.push(packet.buf);
296
+ this.savedPackets.push(packet);
293
297
  }
294
- this.startPacket(this.savedBuffers[this.savedBufferPos++]);
298
+ this.startPacket(this.savedPackets[this.savedPacketPos++]);
295
299
  }
296
300
 
297
301
  /**
@@ -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 {
@@ -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
@@ -166,6 +165,9 @@ async function createNode(str) {
166
165
  case "DESCRIPTION_LIST":
167
166
  navobj = new NavDescriptionList();
168
167
  break;
168
+ default:
169
+ errors.throwErr(errors.ERR_INVALID_CONNECT_STRING_PARAMETERS,
170
+ `unknown top element ${arg}`);
169
171
  }
170
172
  navobj.initFromNVPair(nvpair);
171
173
  let cs = new ConnStrategy();
@@ -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))"
@@ -145,8 +144,9 @@ 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");
@@ -216,8 +216,12 @@ class EZConnectResolver {
216
216
  let ipcnt = 0;
217
217
  let 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';
@@ -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,
@@ -443,7 +444,6 @@ const NavSchemaObject = {
443
444
  LB: "(LOAD_BALANCE=yes)",
444
445
  NFO: "(FAILOVER=false)",
445
446
  CD: "(CONNECT_DATA=",
446
- CID: `(CID=(PROGRAM=nodejs)(HOST=${os.hostname()})(USER=${os.userInfo().username}))`,
447
447
  CONID: "(CONNECTION_ID="
448
448
  };
449
449
  const options = {
@@ -770,10 +770,10 @@ class NavDescription extends Description {
770
770
  if (this.connectData == null) {
771
771
  this.connectData = "(SERVICE_NAME=)";
772
772
  }
773
-
773
+ const cid = `(CID=(PROGRAM=${cInfo.program})(HOST=${cInfo.hostName})(USER=${cInfo.userName}))`;
774
774
  cOpts[i].CNdata.push(NavSchemaObject.CD);
775
775
  cOpts[i].CNdata.push(this.connectData);
776
- cOpts[i].CNdata.push(NavSchemaObject.CID);
776
+ cOpts[i].CNdata.push(cid);
777
777
  cOpts[i].CNdata.push(")");
778
778
 
779
779
  if (this.SID != null) {
@@ -165,6 +165,9 @@ class NetworkSession {
165
165
  * Make the transport level connection
166
166
  */
167
167
  async transportConnect(address) {
168
+ if (address.protocol.toUpperCase() == 'TCP' && address.httpsProxy) {
169
+ errors.throwErr(errors.ERR_INVALID_CONNECT_STRING_PARAMETERS, 'https proxy requires protocol as', 'tcps ');
170
+ }
168
171
  if (address.protocol && (address.protocol.toUpperCase() == 'TCP' || address.protocol.toUpperCase() == 'TCPS')) {
169
172
  this.ntAdapter = new NTTCP(this.sAtts.nt);
170
173
  } else {
@@ -173,8 +176,8 @@ class NetworkSession {
173
176
  await this.ntAdapter.connect(address);
174
177
  this.ntAdapter.startRead();
175
178
  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);
179
+ this.sndDatapkt = new Packet.DataPacket(this.sAtts.largeSDU);
180
+ this.rcvDatapkt = new Packet.DataPacket(this.sAtts.largeSDU);
178
181
  }
179
182
 
180
183
  /**
@@ -280,17 +283,16 @@ class NetworkSession {
280
283
  }
281
284
 
282
285
  connectPkt = new Packet.ConnectPacket(redirConnData, this.sAtts, constants.NSPFRDR);
286
+ this.sndDatapkt = new Packet.DataPacket(this.sAtts.largeSDU);
283
287
  this._sendConnect(connectPkt);
284
288
  }
285
289
  }
286
290
 
287
291
  /* Accepted */
288
292
  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();
293
+ this.cData = null;
294
+ this.sndDatapkt = new Packet.DataPacket(this.sAtts.largeSDU);
295
+ this.sndDatapkt.createPacket(constants.NSPDADAT); //Currently only used for disconnect
294
296
  this.sndDatapkt.offset = this.sndDatapkt.dataPtr;
295
297
  this.sndDatapkt.len = this.sndDatapkt.bufLen;
296
298
  this.markerPkt = new Packet.MarkerPacket(this.sAtts.largeSDU);
@@ -466,7 +468,7 @@ class NetworkSession {
466
468
  let bytesCopied = 0;
467
469
 
468
470
  this.sndDatapkt.dataLen = this.sndDatapkt.offset;
469
- if (this.sndDatapkt.dataLen < this.sndDatapkt.bufLen) {
471
+ if (this.sndDatapkt.dataLen < this.sndDatapkt.bufLen || !this.sndDatapkt.bufLen) {
470
472
  bytesCopied = this.sndDatapkt.fillBuf(userBuf, offset, len);
471
473
  len -= bytesCopied;
472
474
  offset += bytesCopied;
@@ -591,7 +593,6 @@ class NetworkSession {
591
593
  let error = 0;
592
594
  if (this.controlPkt.errno) { /* Control pkt already read */
593
595
  error = this.controlPkt.errno;
594
- this.controlPkt.clear(); /* Clear error */
595
596
  return (error);
596
597
  } else if (!this.getOption(constants.HEALTHCHECK)) {
597
598
  return errors.ERR_CONNECTION_CLOSED;
@@ -602,7 +603,6 @@ class NetworkSession {
602
603
  if (packet.type == constants.NSPTCNL) {
603
604
  this.controlPkt.fromPacket(packet);
604
605
  error = this.controlPkt.errno;
605
- this.controlPkt.clear(); /* Clear error */
606
606
  return (error);
607
607
  } else {
608
608
  this.ntAdapter.packets.unshift(packet); /* Push packet back */
@@ -47,6 +47,8 @@ const TCPCHA = 1 << 1 | /* ASYNC support */
47
47
  1 << 9 | /* Full Duplex support */
48
48
  1 << 12; /* SIGPIPE Support */
49
49
 
50
+ let streamNum = 1;
51
+
50
52
  /**
51
53
  * Network Transport TCP/TCPS adapter
52
54
  * @param {Address} address Destination Address
@@ -63,6 +65,8 @@ class NTTCP {
63
65
  this.numPacketsSinceLastWait = 0;
64
66
  this.secure = false;
65
67
  this.largeSDU = false;
68
+ this.streamNum = streamNum++;
69
+ this.packetNum = 1;
66
70
  }
67
71
 
68
72
  /**
@@ -240,7 +244,8 @@ class NTTCP {
240
244
  }
241
245
  this.stream = null;
242
246
  this.connected = false;
243
- this.waiter = null;
247
+ this.drainWaiter = null;
248
+ this.readWaiter = null;
244
249
  }
245
250
 
246
251
  /**
@@ -318,21 +323,19 @@ class NTTCP {
318
323
  send(buf) {
319
324
  this.checkErr();
320
325
  if (process.env.NODE_ORACLEDB_DEBUG_PACKETS)
321
- this.printPacket("Sending packet", buf);
326
+ this.printPacket(`Sending packet ${this.packetNum} on stream ${this.streamNum}`, buf);
322
327
  const result = this.stream.write(buf, (err) => {
323
328
  if (err) {
324
329
  this.savedErr = err;
325
330
  this.err = true;
326
- if (this.waiter) {
327
- this.waiter();
328
- this.waiter = null;
329
- }
331
+ this._notifyWaiters();
330
332
  }
331
333
  });
332
334
  if (!result) {
333
335
  this.needsDrain = true;
334
336
  }
335
337
  this.numPacketsSinceLastWait++;
338
+ this.packetNum++;
336
339
  }
337
340
 
338
341
  /**
@@ -353,11 +356,7 @@ class NTTCP {
353
356
  this.checkErr();
354
357
  if (this.needsDrain) {
355
358
  await new Promise((resolve) => {
356
- this.waiter = resolve;
357
- this.stream.once('drain', () => {
358
- resolve();
359
- this.waiter = null;
360
- });
359
+ this.drainWaiter = resolve;
361
360
  });
362
361
  this.checkErr();
363
362
  } else {
@@ -400,15 +399,16 @@ class NTTCP {
400
399
  const packet = {
401
400
  buf: tempBuf.subarray(0, len),
402
401
  type: tempBuf[4],
403
- flags: tempBuf[5]
402
+ flags: tempBuf[5],
403
+ num : this.packetNum++
404
404
  };
405
405
  this.packets.push(packet);
406
- if (this.waiter) {
407
- this.waiter();
408
- this.waiter = null;
406
+ if (this.readWaiter) {
407
+ this.readWaiter();
408
+ this.readWaiter = null;
409
409
  }
410
410
  if (process.env.NODE_ORACLEDB_DEBUG_PACKETS)
411
- this.printPacket("Receiving packet", packet.buf);
411
+ this.printPacket(`Receiving packet ${packet.num} on stream ${this.streamNum}`, packet.buf);
412
412
 
413
413
  // if the packet consumed all of the bytes (most common scenario), then
414
414
  // simply clear the temporary buffer; otherwise, retain whatever bytes
@@ -442,7 +442,7 @@ class NTTCP {
442
442
  if (this.packets.length === 0) {
443
443
  this.checkErr();
444
444
  await new Promise((resolve) => {
445
- this.waiter = resolve;
445
+ this.readWaiter = resolve;
446
446
  this.numPacketsSinceLastWait = 0;
447
447
  });
448
448
  this.checkErr();
@@ -478,26 +478,25 @@ class NTTCP {
478
478
  this.stream.on('error', (err) => {
479
479
  this.savedErr = err;
480
480
  this.err = true;
481
- if (this.waiter) {
482
- this.waiter();
483
- this.waiter = null;
484
- }
481
+ this._notifyWaiters();
485
482
  });
486
483
 
487
484
  this.stream.on('end', () => {
488
485
  this.err = true;
489
- if (this.waiter) {
490
- this.waiter();
491
- this.waiter = null;
492
- }
486
+ this._notifyWaiters();
493
487
  });
494
488
 
495
489
  this.stream.on('close', () => {
496
490
  this.connected = false;
491
+ this._notifyWaiters();
497
492
  });
498
493
 
499
494
  this.stream.on('drain', () => {
500
495
  this.needsDrain = false;
496
+ if (this.drainWaiter) {
497
+ this.drainWaiter();
498
+ this.drainWaiter = null;
499
+ }
501
500
  });
502
501
 
503
502
  }
@@ -522,6 +521,20 @@ class NTTCP {
522
521
  }
523
522
  }
524
523
 
524
+ /**
525
+ * Notify the waiters (drain and read) and reset them, if applicable.
526
+ */
527
+ _notifyWaiters() {
528
+ if (this.drainWaiter) {
529
+ this.drainWaiter();
530
+ this.drainWaiter = null;
531
+ }
532
+ if (this.readWaiter) {
533
+ this.readWaiter();
534
+ this.readWaiter = null;
535
+ }
536
+ }
537
+
525
538
  }
526
539
 
527
540
  module.exports = NTTCP;
@@ -52,7 +52,7 @@ function ConnectPacket(connectData, sAtts, flags = 0) {
52
52
  }
53
53
 
54
54
  /* Building Connect Packet */
55
- this.buf = Buffer.alloc(size);
55
+ this.buf = Buffer.allocUnsafe(size).fill(0);
56
56
  this.buf.writeUInt16BE(size, constants.NSPHDLEN);
57
57
  this.buf.writeUInt8(flags, constants.NSPHDFLGS);
58
58
  this.buf.writeUInt8(constants.NSPTCN, constants.NSPHDTYP);
@@ -142,24 +142,24 @@ function ConnectPacket(connectData, sAtts, flags = 0) {
142
142
  * @param {int} size of Data Packet
143
143
  * @param {boolean} isLargeSDU Large SDU
144
144
  */
145
- function DataPacket(size, isLargeSDU) {
145
+ function DataPacket(isLargeSDU) {
146
146
  this.dataPtr = 0; /* data offset start */
147
147
  this.dataLen = 0; /* data offset end */
148
- this.bufLen = size; /* Length of buffer */
149
148
  this.offset = 0; /* Offset for buffer read/write (fastpath) */
150
149
  this.len = 0; /* Length of buffer read/write (fastpath) */
150
+ this.bufLen = 0; /* Length of buffer */
151
151
 
152
152
  /**
153
153
  * Create the Data Packet(Internal)
154
154
  */
155
- this.createPacket = function() {
155
+ this.createPacket = function(len) {
156
156
  /* Building Data Packet */
157
157
  this.dataPtr = constants.NSPDADAT;
158
158
  this.dataLen = constants.NSPDADAT;
159
-
160
- this.buf = Buffer.alloc(size);
159
+ this.buf = Buffer.allocUnsafe(len).fill(0);
161
160
  this.buf.writeUInt8(0, constants.NSPHDFLGS);
162
161
  this.buf.writeUInt8(constants.NSPTDA, constants.NSPHDTYP);
162
+ this.bufLen = len; /* Length of buffer */
163
163
  };
164
164
 
165
165
  /**
@@ -173,7 +173,7 @@ function DataPacket(size, isLargeSDU) {
173
173
  let bytes2Copy;
174
174
 
175
175
  if (!this.buf) {
176
- this.createPacket();
176
+ this.createPacket(len + constants.NSPDADAT); //Currently NS data packets are being used only in the connect/disconnect phase
177
177
  }
178
178
 
179
179
  if (len > this.bufLen - this.dataLen) {
@@ -377,7 +377,7 @@ function ControlPacket() {
377
377
  } else if (err1 == NSESENDMESG) {
378
378
  this.errno = err1;
379
379
  this.notifLen = err2;
380
- this.notif = Buffer.alloc(err2 + 1);
380
+ this.notif = Buffer.allocUnsafe(err2 + 1).fill(0);
381
381
  this.buf.copy(this.notif, 0, constants.NSPCTLDAT + 12, constants.NSPCTLDAT + 12 + err2);
382
382
  } else {
383
383
  this.errno = err1;