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.
- package/CHANGELOG.md +1 -1849
- package/LICENSE.txt +8 -222
- package/NOTICE.txt +1 -1
- package/README.md +38 -30
- package/SECURITY.md +38 -0
- package/THIRD_PARTY_LICENSES.txt +1 -1
- package/build/Release/oracledb-6.0.0-darwin-x64.node +0 -0
- package/build/Release/oracledb-6.0.0-darwin-x64.node-buildinfo.txt +1 -0
- package/build/Release/oracledb-6.0.0-js-buildinfo.txt +1 -0
- package/build/Release/oracledb-6.0.0-linux-arm64.node +0 -0
- package/build/Release/oracledb-6.0.0-linux-arm64.node-buildinfo.txt +1 -0
- package/build/Release/oracledb-6.0.0-linux-x64.node +0 -0
- package/build/Release/oracledb-6.0.0-linux-x64.node-buildinfo.txt +1 -0
- package/build/Release/oracledb-6.0.0-win32-x64.node +0 -0
- package/build/Release/oracledb-6.0.0-win32-x64.node-buildinfo.txt +1 -0
- package/examples/README.md +113 -0
- package/examples/dbconfig.js +100 -0
- package/examples/example.js +156 -0
- package/index.js +26 -0
- package/lib/aqDeqOptions.js +146 -7
- package/lib/aqEnqOptions.js +59 -7
- package/lib/aqMessage.js +118 -7
- package/lib/aqQueue.js +242 -53
- package/lib/connection.js +1324 -465
- package/lib/constants.js +203 -0
- package/lib/dbObject.js +346 -32
- package/lib/errors.js +781 -0
- package/lib/impl/aqDeqOptions.js +197 -0
- package/lib/impl/aqEnqOptions.js +89 -0
- package/lib/impl/aqMessage.js +134 -0
- package/lib/impl/aqQueue.js +81 -0
- package/lib/impl/connection.js +529 -0
- package/lib/impl/dbObject.js +159 -0
- package/lib/impl/index.js +59 -0
- package/lib/impl/lob.js +85 -0
- package/lib/impl/pool.js +195 -0
- package/lib/impl/resultset.js +223 -0
- package/lib/impl/sodaCollection.js +174 -0
- package/lib/impl/sodaDatabase.js +81 -0
- package/lib/impl/sodaDocCursor.js +63 -0
- package/lib/impl/sodaDocument.js +98 -0
- package/lib/impl/sodaOperation.js +109 -0
- package/lib/lob.js +156 -68
- package/lib/oracledb.js +1051 -257
- package/lib/pool.js +654 -465
- package/lib/poolStatistics.js +23 -9
- package/lib/queryStream.js +14 -7
- package/lib/resultset.js +292 -171
- package/lib/settings.js +191 -0
- package/lib/sodaCollection.js +214 -201
- package/lib/sodaDatabase.js +107 -71
- package/lib/sodaDocCursor.js +44 -32
- package/lib/sodaDocument.js +76 -14
- package/lib/sodaOperation.js +131 -118
- package/lib/thin/connection.js +1038 -0
- package/lib/thin/dbObject.js +629 -0
- package/lib/thin/index.js +40 -0
- package/lib/thin/lob.js +188 -0
- package/lib/thin/pool.js +481 -0
- package/lib/thin/protocol/buffer.js +1040 -0
- package/lib/thin/protocol/capabilities.js +116 -0
- package/lib/thin/protocol/constants.js +764 -0
- package/lib/thin/protocol/encryptDecrypt.js +185 -0
- package/lib/thin/protocol/messages/auth.js +348 -0
- package/lib/thin/protocol/messages/base.js +475 -0
- package/lib/thin/protocol/messages/commit.js +56 -0
- package/lib/thin/protocol/messages/dataType.js +382 -0
- package/lib/thin/protocol/messages/execute.js +312 -0
- package/lib/thin/protocol/messages/fetch.js +60 -0
- package/lib/thin/protocol/messages/index.js +53 -0
- package/lib/thin/protocol/messages/lobOp.js +200 -0
- package/lib/thin/protocol/messages/logOff.js +53 -0
- package/lib/thin/protocol/messages/ping.js +56 -0
- package/lib/thin/protocol/messages/protocol.js +78 -0
- package/lib/thin/protocol/messages/rollback.js +56 -0
- package/lib/thin/protocol/messages/sessionRelease.js +60 -0
- package/lib/thin/protocol/messages/withData.js +811 -0
- package/lib/thin/protocol/oson.js +660 -0
- package/lib/thin/protocol/packet.js +520 -0
- package/lib/thin/protocol/protocol.js +202 -0
- package/lib/thin/protocol/utils.js +88 -0
- package/lib/thin/resultSet.js +122 -0
- package/lib/thin/sqlnet/connStrategy.js +175 -0
- package/lib/thin/sqlnet/constants.js +199 -0
- package/lib/thin/sqlnet/ezConnectResolver.js +488 -0
- package/lib/thin/sqlnet/navNodes.js +870 -0
- package/lib/thin/sqlnet/networkSession.js +620 -0
- package/lib/thin/sqlnet/ntTcp.js +525 -0
- package/lib/thin/sqlnet/nvStrToNvPair.js +783 -0
- package/lib/thin/sqlnet/packet.js +405 -0
- package/lib/thin/sqlnet/paramParser.js +205 -0
- package/lib/thin/sqlnet/sessionAtts.js +160 -0
- package/lib/thin/statement.js +301 -0
- package/lib/thin/util.js +289 -0
- package/lib/transformer.js +250 -0
- package/lib/types.js +357 -0
- package/lib/util.js +194 -108
- package/lib/version.js +36 -0
- package/package/README.md +33 -30
- package/package/install.js +89 -64
- package/package/prunebinaries.js +60 -12
- package/package.json +3 -3
- package/build/Release/oracledb-5.4.0-darwin-x64.node +0 -0
- package/build/Release/oracledb-5.4.0-darwin-x64.node-buildinfo.txt +0 -1
- package/build/Release/oracledb-5.4.0-linux-x64.node +0 -0
- package/build/Release/oracledb-5.4.0-linux-x64.node-buildinfo.txt +0 -1
- package/build/Release/oracledb-5.4.0-win32-x64.node +0 -0
- 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
|
+
};
|