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