oracledb 5.5.0 → 6.0.1

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 (107) hide show
  1. package/CHANGELOG.md +1 -1875
  2. package/LICENSE.txt +8 -222
  3. package/NOTICE.txt +1 -1
  4. package/README.md +38 -30
  5. package/SECURITY.md +38 -0
  6. package/build/Release/oracledb-6.0.1-darwin-x64.node +0 -0
  7. package/build/Release/oracledb-6.0.1-darwin-x64.node-buildinfo.txt +1 -0
  8. package/build/Release/oracledb-6.0.1-js-buildinfo.txt +1 -0
  9. package/build/Release/oracledb-6.0.1-linux-arm64.node +0 -0
  10. package/build/Release/oracledb-6.0.1-linux-arm64.node-buildinfo.txt +1 -0
  11. package/build/Release/oracledb-6.0.1-linux-x64.node +0 -0
  12. package/build/Release/oracledb-6.0.1-linux-x64.node-buildinfo.txt +1 -0
  13. package/build/Release/oracledb-6.0.1-win32-x64.node +0 -0
  14. package/build/Release/oracledb-6.0.1-win32-x64.node-buildinfo.txt +1 -0
  15. package/examples/README.md +113 -0
  16. package/examples/dbconfig.js +100 -0
  17. package/examples/example.js +156 -0
  18. package/index.js +26 -0
  19. package/lib/aqDeqOptions.js +148 -8
  20. package/lib/aqEnqOptions.js +59 -7
  21. package/lib/aqMessage.js +118 -7
  22. package/lib/aqQueue.js +243 -53
  23. package/lib/connection.js +1326 -465
  24. package/lib/constants.js +203 -0
  25. package/lib/dbObject.js +346 -32
  26. package/lib/errors.js +785 -0
  27. package/lib/impl/aqDeqOptions.js +197 -0
  28. package/lib/impl/aqEnqOptions.js +89 -0
  29. package/lib/impl/aqMessage.js +134 -0
  30. package/lib/impl/aqQueue.js +81 -0
  31. package/lib/impl/connection.js +529 -0
  32. package/lib/impl/dbObject.js +159 -0
  33. package/lib/impl/index.js +59 -0
  34. package/lib/impl/lob.js +85 -0
  35. package/lib/impl/pool.js +195 -0
  36. package/lib/impl/resultset.js +223 -0
  37. package/lib/impl/sodaCollection.js +174 -0
  38. package/lib/impl/sodaDatabase.js +81 -0
  39. package/lib/impl/sodaDocCursor.js +63 -0
  40. package/lib/impl/sodaDocument.js +98 -0
  41. package/lib/impl/sodaOperation.js +109 -0
  42. package/lib/lob.js +157 -68
  43. package/lib/oracledb.js +1047 -345
  44. package/lib/pool.js +654 -465
  45. package/lib/poolStatistics.js +24 -9
  46. package/lib/queryStream.js +16 -8
  47. package/lib/resultset.js +291 -183
  48. package/lib/settings.js +191 -0
  49. package/lib/sodaCollection.js +214 -201
  50. package/lib/sodaDatabase.js +108 -71
  51. package/lib/sodaDocCursor.js +44 -32
  52. package/lib/sodaDocument.js +76 -14
  53. package/lib/sodaOperation.js +131 -118
  54. package/lib/thin/connection.js +1043 -0
  55. package/lib/thin/dbObject.js +630 -0
  56. package/lib/thin/index.js +40 -0
  57. package/lib/thin/lob.js +189 -0
  58. package/lib/thin/pool.js +481 -0
  59. package/lib/thin/protocol/buffer.js +1043 -0
  60. package/lib/thin/protocol/capabilities.js +121 -0
  61. package/lib/thin/protocol/constants.js +765 -0
  62. package/lib/thin/protocol/encryptDecrypt.js +185 -0
  63. package/lib/thin/protocol/messages/auth.js +349 -0
  64. package/lib/thin/protocol/messages/base.js +476 -0
  65. package/lib/thin/protocol/messages/commit.js +56 -0
  66. package/lib/thin/protocol/messages/dataType.js +391 -0
  67. package/lib/thin/protocol/messages/execute.js +312 -0
  68. package/lib/thin/protocol/messages/fetch.js +60 -0
  69. package/lib/thin/protocol/messages/index.js +53 -0
  70. package/lib/thin/protocol/messages/lobOp.js +201 -0
  71. package/lib/thin/protocol/messages/logOff.js +53 -0
  72. package/lib/thin/protocol/messages/ping.js +56 -0
  73. package/lib/thin/protocol/messages/protocol.js +78 -0
  74. package/lib/thin/protocol/messages/rollback.js +56 -0
  75. package/lib/thin/protocol/messages/sessionRelease.js +60 -0
  76. package/lib/thin/protocol/messages/withData.js +812 -0
  77. package/lib/thin/protocol/oson.js +661 -0
  78. package/lib/thin/protocol/packet.js +519 -0
  79. package/lib/thin/protocol/protocol.js +202 -0
  80. package/lib/thin/protocol/utils.js +89 -0
  81. package/lib/thin/resultSet.js +122 -0
  82. package/lib/thin/sqlnet/connStrategy.js +175 -0
  83. package/lib/thin/sqlnet/constants.js +199 -0
  84. package/lib/thin/sqlnet/ezConnectResolver.js +488 -0
  85. package/lib/thin/sqlnet/navNodes.js +870 -0
  86. package/lib/thin/sqlnet/networkSession.js +621 -0
  87. package/lib/thin/sqlnet/ntTcp.js +527 -0
  88. package/lib/thin/sqlnet/nvStrToNvPair.js +783 -0
  89. package/lib/thin/sqlnet/packet.js +405 -0
  90. package/lib/thin/sqlnet/paramParser.js +206 -0
  91. package/lib/thin/sqlnet/sessionAtts.js +160 -0
  92. package/lib/thin/statement.js +300 -0
  93. package/lib/thin/util.js +289 -0
  94. package/lib/transformer.js +252 -0
  95. package/lib/types.js +357 -0
  96. package/lib/util.js +196 -110
  97. package/lib/version.js +36 -0
  98. package/package/README.md +33 -30
  99. package/package/install.js +89 -64
  100. package/package/prunebinaries.js +60 -12
  101. package/package.json +3 -3
  102. package/build/Release/oracledb-5.5.0-darwin-x64.node +0 -0
  103. package/build/Release/oracledb-5.5.0-darwin-x64.node-buildinfo.txt +0 -1
  104. package/build/Release/oracledb-5.5.0-linux-x64.node +0 -0
  105. package/build/Release/oracledb-5.5.0-linux-x64.node-buildinfo.txt +0 -1
  106. package/build/Release/oracledb-5.5.0-win32-x64.node +0 -0
  107. package/build/Release/oracledb-5.5.0-win32-x64.node-buildinfo.txt +0 -1
@@ -0,0 +1,621 @@
1
+ // Copyright (c) 2022, 2023, Oracle and/or its affiliates.
2
+
3
+ //-----------------------------------------------------------------------------
4
+ //
5
+ // This software is dual-licensed to you under the Universal Permissive License
6
+ // (UPL) 1.0 as shown at https://oss.oracle.com/licenses/upl and Apache License
7
+ // 2.0 as shown at http://www.apache.org/licenses/LICENSE-2.0. You may choose
8
+ // either license.
9
+ //
10
+ // If you elect to accept the software under the Apache License, Version 2.0,
11
+ // the following applies:
12
+ //
13
+ // Licensed under the Apache License, Version 2.0 (the "License");
14
+ // you may not use this file except in compliance with the License.
15
+ // You may obtain a copy of the License at
16
+ //
17
+ // https://www.apache.org/licenses/LICENSE-2.0
18
+ //
19
+ // Unless required by applicable law or agreed to in writing, software
20
+ // distributed under the License is distributed on an "AS IS" BASIS,
21
+ // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
22
+ // See the License for the specific language governing permissions and
23
+ // limitations under the License.
24
+ //
25
+ //-----------------------------------------------------------------------------
26
+
27
+ 'use strict';
28
+
29
+ const Packet = require("./packet.js");
30
+ const NTTCP = require("./ntTcp.js");
31
+ const SessionAtts = require("./sessionAtts.js");
32
+ const constants = require("./constants.js");
33
+ const { createNode } = require('./connStrategy.js');
34
+ const errors = require("../../errors.js");
35
+ const { findNVPairRecurse, createNVPair, findValue } = require("./nvStrToNvPair.js");
36
+ const { Buffer } = require('buffer');
37
+ const EzConnect = require("./ezConnectResolver.js");
38
+ const { NLParamParser, tnsnamesFilePath } = require("./paramParser.js");
39
+ const process = require('process');
40
+
41
+ /**
42
+ *
43
+ * @param {string} userConfig
44
+ * @returns serverinfo
45
+ */
46
+
47
+ async function getConnectionInfo(userConfig) {
48
+ let connStr = await resolveConnectStr(userConfig.connectString, userConfig.configDir);
49
+ let nvpair;
50
+ if (typeof connStr === 'string')
51
+ nvpair = createNVPair(connStr);
52
+ else
53
+ nvpair = connStr;//Already a NVPair
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"]);
59
+
60
+ return [serverVal, connClass, svcname, poolPurity ];
61
+ }
62
+
63
+ /**
64
+ * Resolve the connect string to a NV format address
65
+ * @param {String} connStr Connect string
66
+ * @returns AddressNode
67
+ */
68
+ let nlParamParser = new NLParamParser;
69
+ async function resolveConnectStr(connectString, configDir) {
70
+ let connStr = connectString.trim();
71
+ let resolvedVal = connStr;
72
+ if ((connStr.indexOf(')') == -1) || (connStr.indexOf('(') != 0)) {
73
+ try {
74
+ /* Try through ezconnect */
75
+ let ezcnObj = new EzConnect(connStr);
76
+ resolvedVal = await ezcnObj.getResolvedUrl();
77
+ } catch (err) {
78
+ try {
79
+ /* try tns alias */
80
+ let namesFilePath = tnsnamesFilePath(configDir);
81
+ let 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);
86
+ } catch (err1) {
87
+ if ((connStr.indexOf(':') != -1) || (connStr.indexOf('/') != -1)) {
88
+ throw err;
89
+ } else {
90
+ throw err1;
91
+ }
92
+ }
93
+ }
94
+ }
95
+ return resolvedVal;
96
+ }
97
+
98
+ async function resolveAddress(connStr, configDir) {
99
+ let connstr = await resolveConnectStr(connStr, configDir);
100
+ return createNode(connstr);
101
+ }
102
+
103
+ /**
104
+ * Timeout function
105
+ * @param {Promise} asyncPromise input promise
106
+ * @param {int} timeVal timeout value
107
+ * @returns resolved value of input promise
108
+ */
109
+ function timeout(asyncPromise, timeVal, oper, address, connID) {
110
+ let timer;
111
+
112
+ const timeoutPromise = new Promise((resolve, reject) => {
113
+ // max possible value for 32-bit integer
114
+ if (timeVal > 2147483647)
115
+ timeVal = 2147483647;
116
+
117
+ timer = setTimeout(() => reject(errors.getErr(errors.ERR_CONNECTION_TIMEDOUT, address.host, address.port, oper, timeVal / 1000, connID)), timeVal);
118
+ });
119
+ return Promise.race([asyncPromise, timeoutPromise]).then((result) => {
120
+ clearTimeout(timer);
121
+ return result;
122
+ }).catch((err) => {
123
+ clearTimeout(timer);
124
+ throw err;
125
+ });
126
+ }
127
+
128
+ /**
129
+ * Network Session. This will be used for communication with the server.
130
+ * @param {object} userConfig Connection options
131
+ */
132
+ class NetworkSession {
133
+
134
+ constructor() {
135
+ this.connected = false;
136
+ this.isBreak = false;
137
+ this.isReset = false;
138
+ this.breakPosted = false;
139
+ }
140
+
141
+ async getAddress(addressNode, userConfig) {
142
+ /* Get the next address */
143
+ let address = await addressNode.execute(userConfig);
144
+ /* Prepare connection attributes */
145
+ let uuid = this.sAtts ? this.sAtts.uuid : null;
146
+ this.sAtts = new SessionAtts(uuid);
147
+ this.sAtts.setFrom(userConfig);
148
+ this.sAtts.setFrom(address.desc.params); /* Resolve attributes from Connect String */
149
+ await this.sAtts.prepare(address.protocol);
150
+
151
+ /* 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);
156
+ cdataNVPair.addListElement(childNVPair);
157
+
158
+ this.cData = Buffer.from(rootNVPair.toString(), 'ascii');
159
+ this.cDataNVPair = rootNVPair;
160
+
161
+ return (address);
162
+ }
163
+
164
+ /**
165
+ * Make the transport level connection
166
+ */
167
+ async transportConnect(address) {
168
+ if (address.protocol && (address.protocol.toUpperCase() == 'TCP' || address.protocol.toUpperCase() == 'TCPS')) {
169
+ this.ntAdapter = new NTTCP(this.sAtts.nt);
170
+ } else {
171
+ errors.throwErr(errors.ERR_INVALID_CONNECT_STRING_PARAMETERS, address.protocol + " protocol not supported");
172
+ }
173
+ await this.ntAdapter.connect(address);
174
+ this.ntAdapter.startRead();
175
+ 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);
178
+ }
179
+
180
+ /**
181
+ * Send the NSPTCN(connect) packet
182
+ * @param {object} connectPkt Connect Packet
183
+ */
184
+ _sendConnect(connectPkt) {
185
+ this._sendPacket(connectPkt.buf);
186
+ if (connectPkt.overflow) {
187
+ this._send(connectPkt.connectData, 0, connectPkt.connectDataLen);
188
+ this.flush();
189
+ }
190
+ }
191
+
192
+ /**
193
+ * Establish network session .Make transport level connection, send NSPTCN(connect packet) and read the response.
194
+ * @returns NetError.(connection successfully established(NetError.CONNECTED) or reason for failure)
195
+ */
196
+ async connect2(address) {
197
+ /* Sanitise SDU */
198
+ if (this.sAtts.sdu) {
199
+ if (this.sAtts.sdu > constants.NSPABSSDULN) {
200
+ this.sAtts.sdu = constants.NSPABSSDULN;
201
+ } else if (this.sAtts.sdu < constants.NSPMNSDULN) {
202
+ this.sAtts.sdu = constants.NSPMNSDULN;
203
+ }
204
+ } else {
205
+ this.sAtts.sdu = constants.NSPDFSDULN;
206
+ }
207
+
208
+ /* Transport connect */
209
+ if (this.sAtts.transportConnectTimeout) {
210
+ let asyncPromise = this.transportConnect(address);
211
+ await timeout(asyncPromise, this.sAtts.transportConnectTimeout, "transportConnectTimeout", address, this.sAtts.connectionId);
212
+ } else {
213
+ await this.transportConnect(address);
214
+ }
215
+
216
+ /* Send the connect packet */
217
+ let connectPkt = new Packet.ConnectPacket(this.cData, this.sAtts);
218
+ this._sendConnect(connectPkt);
219
+
220
+ /* Read the response */
221
+ while (true) { // eslint-disable-line
222
+ const packet = await this._recvPacket();
223
+ if (packet.type === constants.NSPTAC) /* ACCEPT */
224
+ break;
225
+ if (packet.type === constants.NSPTRF) { /* REFUSE */
226
+ if (this.refusePkt.overflow) {
227
+ await this._recvPacket();
228
+ this.refusePkt.dataBuf = this.rcvDatapkt.buf.subarray(this.rcvDatapkt.offset, this.rcvDatapkt.len).toString();
229
+ }
230
+ let nvpair = createNVPair(this.refusePkt.dataBuf);
231
+ this.refusePkt = null;
232
+ let err = findValue(nvpair, ["DESCRIPTION", "ERR"]);
233
+ if (err == "12514") {
234
+ errors.throwErr(errors.ERR_INVALID_SERVICE_NAME, this.getOption(constants.SVCNAME), address.host, address.port, this.sAtts.connectionId);
235
+ } else if (err == "12505") {
236
+ errors.throwErr(errors.ERR_INVALID_SID, this.getOption(constants.SID), address.host, address.port, this.sAtts.connectionId);
237
+ } else if (err) {
238
+ errors.throwErr(errors.ERR_CONNECTION_REFUSED, address.host, address.port, this.sAtts.connectionId, "ORA-" + err);
239
+ } else {
240
+ errors.throwErr(errors.ERR_CONNECTION_REFUSED, address.host, address.port, this.sAtts.connectionId, "refused");
241
+ }
242
+ } else if (packet.type === constants.NSPTRS) { /* RESEND */
243
+ if ((packet.flags & constants.NSPFSRN) == constants.NSPFSRN) {
244
+ await this.ntAdapter.renegTLS();
245
+ this.ntAdapter.startRead();
246
+ }
247
+ this._sendConnect(connectPkt);
248
+ } else if (packet.type === constants.NSPTRD) { /* REDIRECT */
249
+ let adrLen, adrStr, redirAddressNode, redirConnData;
250
+
251
+ /* Read and connect to Redirect address */
252
+ if (this.redirectPkt.overflow) {
253
+ await this._recvPacket();
254
+ this.redirectPkt.dataBuf = this.rcvDatapkt.buf.subarray(this.rcvDatapkt.offset, this.rcvDatapkt.len);
255
+ }
256
+
257
+ if (this.redirectPkt.flags & constants.NSPFRDS) {
258
+ adrLen = this.redirectPkt.dataBuf.indexOf('\0', 0, 'ascii');
259
+ adrStr = this.redirectPkt.dataBuf.toString('ascii', 0, adrLen);
260
+ redirConnData = this.redirectPkt.dataBuf.subarray(adrLen + 1, this.redirectPkt.dataLen);
261
+ } else {
262
+ adrStr = this.redirectPkt.dataBuf.toString('ascii');
263
+ redirConnData = this.cData;
264
+ }
265
+
266
+ redirAddressNode = await resolveAddress(adrStr);
267
+ let host = address.host;
268
+ address = await redirAddressNode.execute();
269
+ if (address.desc)
270
+ this.sAtts.setFrom(address.desc.params); /* Add on attributes from redirect connect String */
271
+ address.originHost = host;
272
+ this.redirectPkt = null;
273
+ this.ntAdapter.disconnect(constants.NSFIMM);
274
+
275
+ if (this.sAtts.transportConnectTimeout) {
276
+ let asyncPromise = this.transportConnect(address);
277
+ await timeout(asyncPromise, this.sAtts.transportConnectTimeout, "transportConnectTimeout", address, this.sAtts.connectionId);
278
+ } else {
279
+ await this.transportConnect(address);
280
+ }
281
+
282
+ connectPkt = new Packet.ConnectPacket(redirConnData, this.sAtts, constants.NSPFRDR);
283
+ this._sendConnect(connectPkt);
284
+ }
285
+ }
286
+
287
+ /* Accepted */
288
+ 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();
294
+ this.sndDatapkt.offset = this.sndDatapkt.dataPtr;
295
+ this.sndDatapkt.len = this.sndDatapkt.bufLen;
296
+ this.markerPkt = new Packet.MarkerPacket(this.sAtts.largeSDU);
297
+ this.controlPkt = new Packet.ControlPacket();
298
+ this.ntAdapter.largeSDU = this.sAtts.largeSDU;
299
+ this.sAtts.nt.wallet = null;
300
+ this.sAtts.nt.walletPassword = null;
301
+ return (true);
302
+ }
303
+
304
+ /**
305
+ * Try all available addresses for connection establishment
306
+ */
307
+ async connect1(address, addressNode, userConfig) {
308
+ let connected, savedErr;
309
+ do {
310
+ try {
311
+ if (this.sAtts.connectTimeout) {
312
+ let asyncPromise = this.connect2(address);
313
+ connected = await timeout(asyncPromise, this.sAtts.connectTimeout, "connectTimeout", address, this.sAtts.connectionId);
314
+ } else {
315
+ connected = await this.connect2(address);
316
+ }
317
+ } catch (err) {
318
+ if (err.message.startsWith('NJS-510')) {
319
+ this.ntAdapter.connected = true; // Pretend as connected
320
+ }
321
+ if (this.ntAdapter) {
322
+ this.ntAdapter.disconnect(constants.NSFIMM);
323
+ this.ntAdapter = null;
324
+ }
325
+ connected = false;
326
+ savedErr = err;
327
+ try {
328
+ address = await this.getAddress(addressNode, userConfig);
329
+ } catch (err) {
330
+ break;
331
+ }
332
+ }
333
+ } while (!connected);
334
+ if (connected) {
335
+ return;
336
+ } else {
337
+ throw (savedErr);
338
+ }
339
+ }
340
+
341
+ /**
342
+ * Process packet (Internal)
343
+ */
344
+ _processPacket(packet) {
345
+ switch (packet.type) {
346
+ case constants.NSPTDA: /* DATA packet */
347
+ this.rcvDatapkt.fromPacket(packet);
348
+ break;
349
+ case constants.NSPTMK: /* MARKER packet */
350
+ this.markerPkt.fromPacket(packet, this);
351
+ break;
352
+ case constants.NSPTCNL: /* CONTROL packet */
353
+ this.controlPkt.fromPacket(packet);
354
+ break;
355
+ case constants.NSPTAC: /* ACCEPT */
356
+ Packet.AcceptPacket(packet, this.sAtts);
357
+ break;
358
+ case constants.NSPTRF: /* REFUSE */
359
+ this.refusePkt = new Packet.RefusePacket(packet);
360
+ break;
361
+ case constants.NSPTRS: /* RESEND */
362
+ break;
363
+ case constants.NSPTRD: /* REDIRECT */
364
+ this.redirectPkt = new Packet.RedirectPacket(packet);
365
+ break;
366
+ default:
367
+ errors.throwErr(errors.ERR_CONNECTION_INVALID_PACKET);
368
+ }
369
+ }
370
+
371
+ /**
372
+ * Receive packet (Internal)
373
+ * Control packets are consumed internally and discarded
374
+ */
375
+ async _recvPacket() {
376
+ while (true) { // eslint-disable-line
377
+ const packet = await this.ntAdapter.receive();
378
+ if (!packet)
379
+ break;
380
+ this._processPacket(packet);
381
+ if (packet.type !== constants.NSPTCNL)
382
+ return packet;
383
+ }
384
+ }
385
+
386
+ /**
387
+ * Send data (Internal)
388
+ */
389
+ _sendPacket(buf) {
390
+ this.ntAdapter.send(buf);
391
+ }
392
+
393
+ /**
394
+ * Break ongoing operation
395
+ */
396
+ sendBreak() {
397
+ if (this.isBreak)
398
+ return; /* Already in a break */
399
+
400
+ if (!this.connected) {
401
+ this.isBreak = true; /* Not yet connected. Post the break */
402
+ this.breakPosted = true;
403
+ return;
404
+ }
405
+
406
+ this.isBreak = true;
407
+ this.markerPkt.prepare(constants.NSPMKTD1, constants.NIQIMARK);
408
+ this._sendPacket(this.markerPkt.buf);
409
+ }
410
+
411
+ /**
412
+ * Reset the connection
413
+ */
414
+ async reset() {
415
+ /* If posted send Break */
416
+ if (this.breakPosted) {
417
+ this.markerPkt.prepare(constants.NSPMKTD1, constants.NIQBMARK);
418
+ this._sendPacket(this.markerPkt.buf);
419
+ this.breakPosted = false;
420
+ }
421
+ /* Send Reset */
422
+ this.markerPkt.prepare(constants.NSPMKTD1, constants.NIQRMARK);
423
+ this._sendPacket(this.markerPkt.buf);
424
+
425
+ /* Await Reset */
426
+ while (!this.isReset) {
427
+ await this._recvPacket();
428
+ }
429
+
430
+ /* reset packet buffers */
431
+ this.sndDatapkt.dataPtr = this.sndDatapkt.dataLen = constants.NSPDADAT;
432
+ this.sndDatapkt.offset = this.sndDatapkt.dataPtr;
433
+ this.sndDatapkt.len = this.sndDatapkt.bufLen;
434
+
435
+ this.isBreak = this.isReset = false;
436
+ }
437
+
438
+ /**
439
+ * Receive packet
440
+ */
441
+ async recvPacket() {
442
+ return await this._recvPacket();
443
+ }
444
+
445
+ syncRecvPacket() {
446
+ while (this.ntAdapter.packets.length > 0) {
447
+ const packet = this.ntAdapter.syncReceive();
448
+ if (!packet)
449
+ break;
450
+ this._processPacket(packet);
451
+ if (packet.type !== constants.NSPTCNL)
452
+ return packet;
453
+ }
454
+ }
455
+
456
+ /**
457
+ * Send data
458
+ * @param {Buffer} userBuf User provided buffer
459
+ * @param {*} offset from which to send data
460
+ * @param {*} len number of bytes to send
461
+ */
462
+ _send(userBuf, offset, len) {
463
+ if (this.isBreak) {
464
+ return;
465
+ }
466
+ let bytesCopied = 0;
467
+
468
+ this.sndDatapkt.dataLen = this.sndDatapkt.offset;
469
+ if (this.sndDatapkt.dataLen < this.sndDatapkt.bufLen) {
470
+ bytesCopied = this.sndDatapkt.fillBuf(userBuf, offset, len);
471
+ len -= bytesCopied;
472
+ offset += bytesCopied;
473
+ this.sndDatapkt.offset = this.sndDatapkt.dataLen;
474
+ }
475
+
476
+ while (len) {
477
+ this._sendPacket(this.sndDatapkt.dataBuf);
478
+
479
+ /* If break throw error now */
480
+ if (this.isBreak) {
481
+ return;
482
+ }
483
+
484
+ this.sndDatapkt.dataLen = this.sndDatapkt.dataPtr;
485
+ this.sndDatapkt.offset = this.sndDatapkt.dataPtr;
486
+ bytesCopied = this.sndDatapkt.fillBuf(userBuf, offset, len);
487
+ len -= bytesCopied;
488
+ offset += bytesCopied;
489
+ this.sndDatapkt.offset = this.sndDatapkt.dataLen;
490
+ }
491
+ }
492
+
493
+ /**
494
+ * Flush send buffers
495
+ */
496
+ flush() {
497
+ if (this.isBreak) {
498
+ return;
499
+ }
500
+ this.sndDatapkt.dataLen = this.sndDatapkt.offset;
501
+ this.sndDatapkt.prepare2Send();
502
+ this._sendPacket(Buffer.from(this.sndDatapkt.dataBuf));
503
+ this.sndDatapkt.dataLen = this.sndDatapkt.dataPtr;
504
+ this.sndDatapkt.offset = this.sndDatapkt.dataPtr;
505
+ }
506
+
507
+ /**
508
+ * Establish network connection
509
+ */
510
+ async connect(userConfig) {
511
+ let connStr = userConfig.connectString ? userConfig.connectString : userConfig.connectionString;
512
+ let addressNode = await resolveAddress(connStr, userConfig.configDir);
513
+ let address;
514
+ try {
515
+ address = await this.getAddress(addressNode, userConfig);
516
+ } catch (err) {
517
+ if (err.message == "All options tried") /* Not even one valid Address */
518
+ errors.throwErr(errors.ERR_INVALID_CONNECT_STRING_PARAMETERS, "Ensure the ADDRESS parameters have been entered correctly, the most likely incorrect parameter is the host name");
519
+ else
520
+ errors.throwErr(errors.ERR_INVALID_CONNECT_STRING_PARAMETERS, err.message);
521
+ }
522
+ await this.connect1(address, addressNode, userConfig);
523
+ }
524
+
525
+ /**
526
+ * Disconnect
527
+ * @param {int} type of disconnect
528
+ */
529
+ disconnect(type) {
530
+ if (!this.connected) {
531
+ return;
532
+ }
533
+ if (type != constants.NSFIMM && !this.ntAdapter.err) {
534
+ /* Send EOF packet */
535
+ this.sndDatapkt.dataLen = this.sndDatapkt.offset;
536
+ this.sndDatapkt.prepare2Send(constants.NSPDAFEOF);
537
+ this._sendPacket(this.sndDatapkt.dataBuf);
538
+ }
539
+ this.ntAdapter.disconnect(type);
540
+ this.ntAdapter = null;
541
+ this.connected = false;
542
+ }
543
+
544
+ /**
545
+ * Get connection attributes
546
+ * @param {int} opcode type of attribute
547
+ * @returns attribute value
548
+ */
549
+ getOption(opcode) {
550
+ switch (opcode) {
551
+
552
+ case constants.NS_MOREDATA: /* Is there more data in read buffers */
553
+ return (this.ntAdapter.packets.length > 0);
554
+
555
+ case constants.SVCNAME: /* Service name */
556
+ return findValue(this.cDataNVPair, ["DESCRIPTION", "CONNECT_DATA", "SERVICE_NAME"]);
557
+
558
+ case constants.SID: /* Service name */
559
+ return findValue(this.cDataNVPair, ["DESCRIPTION", "CONNECT_DATA", "SID"]);
560
+
561
+ case constants.SERVERTYPE: /* Server type */
562
+ return findValue(this.cDataNVPair, ["DESCRIPTION", "CONNECT_DATA", "SERVER"]);
563
+
564
+ case constants.REMOTEADDR: /* Peer address */
565
+ if (this.ntAdapter) {
566
+ return this.ntAdapter.getOption(opcode); // Pass through to NT
567
+ } else {
568
+ return null;
569
+ }
570
+
571
+ case constants.CONNCLASS: /* Connection Class */
572
+ return findValue(this.cDataNVPair, ["DESCRIPTION", "CONNECT_DATA", "POOL_CONNECTION_CLASS"]);
573
+
574
+ case constants.PURITY: /* Purity */
575
+ return findValue(this.cDataNVPair, ["DESCRIPTION", "CONNECT_DATA", "POOL_PURITY"]);
576
+
577
+ case constants.HEALTHCHECK: /* Is connection healthy */
578
+ return (this.connected && this.ntAdapter.connected && !this.ntAdapter.err);
579
+
580
+ default:
581
+ errors.throwErr(errors.ERR_INTERNAL, "getOption not supported for opcode " + opcode);
582
+ }
583
+ }
584
+
585
+ /**
586
+ * receive inband notification
587
+ * @param {Object} obj Return the notification into user provided object
588
+ * @returns Error number sent from server, or error on the connection. returns 0 if healthy connection
589
+ */
590
+ recvInbandNotif() {
591
+ let error = 0;
592
+ if (this.controlPkt.errno) { /* Control pkt already read */
593
+ error = this.controlPkt.errno;
594
+ this.controlPkt.clear(); /* Clear error */
595
+ return (error);
596
+ } else if (!this.getOption(constants.HEALTHCHECK)) {
597
+ return errors.ERR_CONNECTION_CLOSED;
598
+ } else {
599
+ if (this.getOption(constants.NS_MOREDATA)) { //More data available
600
+ const packet = this.ntAdapter.syncReceive();
601
+
602
+ if (packet.type == constants.NSPTCNL) {
603
+ this.controlPkt.fromPacket(packet);
604
+ error = this.controlPkt.errno;
605
+ this.controlPkt.clear(); /* Clear error */
606
+ return (error);
607
+ } else {
608
+ this.ntAdapter.packets.unshift(packet); /* Push packet back */
609
+ return (0);
610
+ }
611
+ } else
612
+ return (0);
613
+ }
614
+ }
615
+ }
616
+
617
+ module.exports = {
618
+ NetworkSession,
619
+ resolveAddress,
620
+ getConnectionInfo
621
+ };