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,527 @@
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 { Buffer } = require('buffer');
30
+ const net = require("net");
31
+ const process = require("process");
32
+ const tls = require("tls");
33
+ const http = require("http");
34
+ const Timers = require('timers');
35
+ const constants = require("./constants.js");
36
+ const errors = require("../../errors.js");
37
+
38
+ const PACKET_HEADER_SIZE = 8;
39
+ const DEFAULT_PORT = 1521;
40
+ const DEFAULT_HTTPS_PROXY_PORT = 80;
41
+
42
+ /* Protocol characteristics */
43
+ const TCPCHA = 1 << 1 | /* ASYNC support */
44
+ 1 << 2 | /* Callback support */
45
+ 1 << 3 | /* More Data support */
46
+ 1 << 8 | /* Read/Write Readiness support */
47
+ 1 << 9 | /* Full Duplex support */
48
+ 1 << 12; /* SIGPIPE Support */
49
+
50
+ /**
51
+ * Network Transport TCP/TCPS adapter
52
+ * @param {Address} address Destination Address
53
+ * @param {Object} atts Transport Attributes
54
+ */
55
+ class NTTCP {
56
+
57
+ constructor(atts) {
58
+ this.atts = atts;
59
+ this.cha = TCPCHA;
60
+ this.connected = false;
61
+ this.err = false;
62
+ this.needsDrain = false;
63
+ this.numPacketsSinceLastWait = 0;
64
+ this.secure = false;
65
+ this.largeSDU = false;
66
+ }
67
+
68
+ /**
69
+ * DN matching funciton(used with TLS)
70
+ */
71
+ dnMatch(serverName, cert) {
72
+ if (this.atts.sslServerDNMatch) {
73
+ let toObject = str =>str .split(',').map(x => x.split('=').map(y => y.trim())).reduce((a, x) => {
74
+ a[x[0]] = x[1];
75
+ return a;
76
+ }, {});
77
+ if (this.atts.sslServerCertDN) { /* Full DN Match */
78
+ let obj = toObject(this.atts.sslServerCertDN);
79
+ for (let key in obj) {
80
+ if (obj[key] != cert.subject[key]) {
81
+ return (errors.getErr(errors.ERR_TLS_DNMATCH_FAILURE));
82
+ }
83
+ }
84
+ } else {
85
+ if (tls.checkServerIdentity(this.hostName, cert) && (!this.originHost || tls.checkServerIdentity(this.originHost, cert))) { /* Hostname match */
86
+ const hostName = this.hostName + " " + (this.originHost ? "or " + this.originHost : "");
87
+ return (errors.getErr(errors.ERR_TLS_HOSTMATCH_FAILURE, hostName));
88
+ }
89
+ }
90
+ }
91
+ }
92
+
93
+ /**
94
+ * TLS connection establishment
95
+ * @returns Promise
96
+ */
97
+ async tlsConnect(secureContext, connStream) {
98
+ this.stream.removeAllListeners();
99
+ let connectErrCause;
100
+ const tlsOptions = {
101
+ host: this.host,
102
+ socket: connStream,
103
+ rejectUnauthorized: true,
104
+ secureContext: secureContext,
105
+ enableTrace: false,
106
+ checkServerIdentity: this.dnMatch.bind(this)
107
+ };
108
+
109
+ await new Promise((resolve) => {
110
+ this.stream = tls.connect(tlsOptions, () => {
111
+ if (!this.stream.authorized) {
112
+ connectErrCause = "server certificate unauthorized";
113
+ }
114
+ resolve();
115
+ }).on('error', (err) => {
116
+ connectErrCause = err.message;
117
+ resolve();
118
+ });
119
+ });
120
+ if (connectErrCause)
121
+ errors.throwErr(errors.ERR_TLS_AUTH_FAILURE, this.host, this.port, this.atts.connectionId, connectErrCause);
122
+ this.connStream = connStream;
123
+ }
124
+
125
+ /**
126
+ * TCP connection establishment
127
+ * @returns Promise
128
+ */
129
+ async ntConnect(address) {
130
+ if (!address.port) {
131
+ address.port = DEFAULT_PORT;
132
+ }
133
+
134
+ let connectErrCause, proxyConnectErrCause, req;
135
+ let httpsProxy = address.httpsProxy || this.atts.httpsProxy;
136
+ let httpsProxyPort = address.httpsProxyPort || this.atts.httpsProxyPort;
137
+
138
+ await new Promise((resolve) => {
139
+ if (httpsProxy) {
140
+ if (!httpsProxyPort) {
141
+ httpsProxyPort = DEFAULT_HTTPS_PROXY_PORT;
142
+ }
143
+ req = http.request({
144
+ host: httpsProxy,
145
+ port: httpsProxyPort,
146
+ method: 'CONNECT',
147
+ path: address.host + ':' + address.port,
148
+ });
149
+ req.once('connect', (res, socket) => {
150
+ if (res.statusCode == 200) {
151
+ this.connected = true;
152
+ this.stream = socket;
153
+ } else {
154
+ proxyConnectErrCause = res.statusCode;
155
+ }
156
+ resolve();
157
+ });
158
+ req.once('error', (err) => {
159
+ proxyConnectErrCause = err.message;
160
+ resolve();
161
+ });
162
+ req.end();
163
+ } else {
164
+ this.stream = net.connect(address.port, address.host, () => {
165
+ this.connected = true;
166
+ resolve();
167
+ });
168
+ this.stream.once('error', (err) => {
169
+ connectErrCause = err.message;
170
+ resolve();
171
+ });
172
+ }
173
+ });
174
+ if (req)
175
+ req.removeAllListeners();
176
+ if (!this.connected) {
177
+ if (proxyConnectErrCause) {
178
+ errors.throwErr(errors.ERR_PROXY_CONNECTION_FAILURE, httpsProxy, httpsProxyPort, this.atts.connectionId, proxyConnectErrCause);
179
+ } else {
180
+ errors.throwErr(errors.ERR_CONNECTION_INCOMPLETE, this.host, this.port, this.atts.connectionId, connectErrCause);
181
+ }
182
+ }
183
+ }
184
+
185
+ /**
186
+ * Network Transport connection establishment
187
+ * @returns Promise
188
+ */
189
+ async connect(address) { /* Connect function for TCP sockets */
190
+ this.originHost = address.originHost;
191
+ this.host = address.host;
192
+ this.hostName = address.hostname;
193
+ this.port = address.port;
194
+
195
+ try {
196
+ await this.ntConnect(address);
197
+ if (this.atts.expireTime || this.atts.enableDCD) { /* Set Keep alives */
198
+ if (this.atts.expireTime) {
199
+ this.stream.setKeepAlive(true, this.atts.expireTime);
200
+ } else {
201
+ this.stream.setKeepAlive(true);
202
+ }
203
+ }
204
+ if (this.atts.tcpNoDelay) { /* Turn off Nagle's unless explicitly enabled by user */
205
+ this.stream.setNoDelay(true);
206
+ }
207
+ if (address.protocol.toUpperCase() == "TCPS") {
208
+ let secureContext;
209
+ this.secure = true;
210
+ try {
211
+ secureContext = tls.createSecureContext({
212
+ cert : this.atts.wallet,
213
+ key : this.atts.wallet,
214
+ passphrase: this.atts.walletPassword,
215
+ ca : this.atts.wallet,
216
+ });
217
+ } catch (err) {
218
+ errors.throwErr(errors.ERR_TLS_INIT_FAILURE);
219
+ }
220
+ await this.tlsConnect(secureContext, this.stream);
221
+ }
222
+ } finally {
223
+ if (this.stream) {
224
+ this.setupEventHandlers();
225
+ }
226
+ }
227
+ }
228
+
229
+ /**
230
+ * Disconnect Network Transoprt
231
+ * @param {int} type
232
+ * @returns Proimise
233
+ */
234
+ disconnect(type) { /* Disconnect function for TCP sockets */
235
+ if (this.connected && !this.err) {
236
+ if (type == constants.NSFIMM)
237
+ this.stream.destroy();
238
+ else
239
+ this.stream.end();
240
+ }
241
+ this.stream = null;
242
+ this.connected = false;
243
+ this.waiter = null;
244
+ }
245
+
246
+ /**
247
+ * Get the string containing a packet dump.
248
+ * @param {Buffer} buffer containing packet data
249
+ */
250
+ getPacketDump(buffer) {
251
+ const lines = [];
252
+ for (let i = 0; i < buffer.length; i += 8) {
253
+ const address = i.toString().padStart(4, '0');
254
+ const block = buffer.slice(i, i + 8);
255
+ const hexDumpValues = [];
256
+ const printableValues = [];
257
+ for (let hexByte of block) {
258
+ hexDumpValues.push(hexByte.toString(16).toUpperCase().padStart(2, '0'));
259
+ if (hexByte > 0x20 && hexByte < 0x7f) {
260
+ printableValues.push(String.fromCharCode(hexByte));
261
+ } else {
262
+ printableValues.push(".");
263
+ }
264
+ }
265
+ while (hexDumpValues.length < 8) {
266
+ hexDumpValues.push(" ");
267
+ printableValues.push(" ");
268
+ }
269
+ const hexValuesBlock = hexDumpValues.join(" ");
270
+ const printableBlock = printableValues.join("");
271
+ lines.push(`${address} : ${hexValuesBlock} |${printableBlock}|`);
272
+ }
273
+ return lines.join("\n");
274
+ }
275
+
276
+ /**
277
+ * Print the packet to the console.
278
+ * @param {String} operation which was performed
279
+ * @param {Buffer} buffer containing packet data
280
+ */
281
+ printPacket(operation, buffer) {
282
+ const now = new Date();
283
+ const formattedDate =
284
+ `${now.getFullYear()}-${now.getMonth().toString().padStart(2, '0')}-` +
285
+ `${now.getDay().toString().padStart(2, '0')} ` +
286
+ `${now.getHours().toString().padStart(2, '0')}:` +
287
+ `${now.getMinutes().toString().padStart(2, '0')}:` +
288
+ `${now.getSeconds().toString().padStart(2, '0')}.` +
289
+ `${now.getMilliseconds().toString().padStart(3, '0')}`;
290
+ const packetDump = this.getPacketDump(buffer);
291
+ console.log(`${formattedDate} ${operation}:\n${packetDump}\n`);
292
+ }
293
+
294
+ /**
295
+ * Check for errors
296
+ */
297
+ checkErr() {
298
+ if (!this.connected || this.err) {
299
+ let err, newErr;
300
+ if (this.savedErr) {
301
+ err = errors.getErr(errors.ERR_CONNECTION_LOSTCONTACT,
302
+ this.host, this.port, this.atts.connectionId, this.savedErr.message);
303
+ } else {
304
+ err = errors.getErr(errors.ERR_CONNECTION_EOF, this.host, this.port, this.atts.connectionId,);
305
+ }
306
+ /* Wrap around NJS-500 */
307
+ newErr = errors.getErr(errors.ERR_CONNECTION_CLOSED);
308
+ newErr.message = newErr.message + "\n" + err.message;
309
+ throw (newErr);
310
+ }
311
+ }
312
+
313
+ /**
314
+ * Transport Send
315
+ * @param {Buffer} buf Buffer to send
316
+ * @returns Promise
317
+ */
318
+ send(buf) {
319
+ this.checkErr();
320
+ if (process.env.NODE_ORACLEDB_DEBUG_PACKETS)
321
+ this.printPacket("Sending packet", buf);
322
+ const result = this.stream.write(buf, (err) => {
323
+ if (err) {
324
+ this.savedErr = err;
325
+ this.err = true;
326
+ if (this.waiter) {
327
+ this.waiter();
328
+ this.waiter = null;
329
+ }
330
+ }
331
+ });
332
+ if (!result) {
333
+ this.needsDrain = true;
334
+ }
335
+ this.numPacketsSinceLastWait++;
336
+ }
337
+
338
+ /**
339
+ * Should writing to the transport be paused? This occurs if draining is
340
+ * required or if the number of packets written since the last pause exceeds
341
+ * 100 (in order to avoid starvation of the event loop during large writes).
342
+ */
343
+ shouldPauseWrite() {
344
+ return (this.needsDrain || this.numPacketsSinceLastWait >= 100);
345
+ }
346
+
347
+ /**
348
+ * Perform a wait -- if draining is required, then until the drain event is
349
+ * emitted or if draining is not required, then a simple setImmediate() that
350
+ * ensures that the event loop is not starved.
351
+ */
352
+ async pauseWrite() {
353
+ this.checkErr();
354
+ if (this.needsDrain) {
355
+ await new Promise((resolve) => {
356
+ this.waiter = resolve;
357
+ this.stream.once('drain', () => {
358
+ resolve();
359
+ this.waiter = null;
360
+ });
361
+ });
362
+ this.checkErr();
363
+ } else {
364
+ await new Promise((resolve) => Timers.setImmediate(resolve));
365
+ }
366
+ this.numPacketsSinceLastWait = 0;
367
+ }
368
+
369
+ /**
370
+ * Start Async reads
371
+ */
372
+ startRead() {
373
+ let tempBuf;
374
+ this.packets = [];
375
+ this.stream.on('data', (chunk) => {
376
+
377
+ // append buffer if previous chunk(s) were insufficient for a full packet
378
+ if (tempBuf) {
379
+ tempBuf = Buffer.concat([tempBuf, chunk]);
380
+ } else {
381
+ tempBuf = chunk;
382
+ }
383
+
384
+ while (tempBuf.length >= PACKET_HEADER_SIZE) {
385
+
386
+ // determine the length of the packet
387
+ let len;
388
+ if (this.largeSDU) {
389
+ len = tempBuf.readUInt32BE();
390
+ } else {
391
+ len = tempBuf.readUInt16BE();
392
+ }
393
+
394
+ // not enough for a full packet so wait for more data to arrive
395
+ if (len > tempBuf.length)
396
+ break;
397
+
398
+ // enough for a full packet, extract details from the packet header
399
+ // and pass them along for processing
400
+ const packet = {
401
+ buf: tempBuf.subarray(0, len),
402
+ type: tempBuf[4],
403
+ flags: tempBuf[5]
404
+ };
405
+ this.packets.push(packet);
406
+ if (this.waiter) {
407
+ this.waiter();
408
+ this.waiter = null;
409
+ }
410
+ if (process.env.NODE_ORACLEDB_DEBUG_PACKETS)
411
+ this.printPacket("Receiving packet", packet.buf);
412
+
413
+ // if the packet consumed all of the bytes (most common scenario), then
414
+ // simply clear the temporary buffer; otherwise, retain whatever bytes
415
+ // are unused and see if sufficient data is available for another
416
+ // packet
417
+ if (len === tempBuf.length) {
418
+ tempBuf = null;
419
+ break;
420
+ } else {
421
+ tempBuf = tempBuf.subarray(len);
422
+ }
423
+
424
+ }
425
+
426
+ });
427
+ }
428
+
429
+ /**
430
+ * Synchronous receive
431
+ * @returns a single packet or undefined if no packets are available
432
+ */
433
+ syncReceive() {
434
+ return this.packets.shift();
435
+ }
436
+
437
+ /**
438
+ * Asynchronous receive
439
+ * @returns a single packet
440
+ */
441
+ async receive() {
442
+ if (this.packets.length === 0) {
443
+ this.checkErr();
444
+ await new Promise((resolve) => {
445
+ this.waiter = resolve;
446
+ this.numPacketsSinceLastWait = 0;
447
+ });
448
+ this.checkErr();
449
+ }
450
+ return this.packets.shift();
451
+ }
452
+
453
+ /**
454
+ * TLS renegotiate
455
+ * @returns Promise
456
+ */
457
+ async renegTLS() {
458
+ try {
459
+ this.checkErr();
460
+ let secureContext = tls.createSecureContext({
461
+ cert : this.atts.wallet,
462
+ key : this.atts.wallet,
463
+ passphrase: this.atts.walletPassword,
464
+ ca : this.atts.wallet,
465
+ });
466
+ await this.tlsConnect(secureContext, this.connStream);
467
+ } finally {
468
+ this.setupEventHandlers();
469
+ }
470
+ }
471
+
472
+ /**
473
+ * Setup handling of events
474
+ */
475
+ setupEventHandlers() {
476
+ this.stream.removeAllListeners();
477
+
478
+ this.stream.on('error', (err) => {
479
+ this.savedErr = err;
480
+ this.err = true;
481
+ if (this.waiter) {
482
+ this.waiter();
483
+ this.waiter = null;
484
+ }
485
+ });
486
+
487
+ this.stream.on('end', () => {
488
+ this.err = true;
489
+ if (this.waiter) {
490
+ this.waiter();
491
+ this.waiter = null;
492
+ }
493
+ });
494
+
495
+ this.stream.on('close', () => {
496
+ this.connected = false;
497
+ });
498
+
499
+ this.stream.on('drain', () => {
500
+ this.needsDrain = false;
501
+ });
502
+
503
+ }
504
+
505
+ /**
506
+ * Get Transport Attributes
507
+ * @param {int} opcode type of attribute
508
+ * @returns attribute value
509
+ */
510
+ getOption(opcode) {
511
+ this.checkErr();
512
+ switch (opcode) {
513
+ case constants.NT_MOREDATA: /* More data available to read */
514
+ return (this.packets.length > 0);
515
+ case constants.REMOTEADDR: /* Remote Address */
516
+ {
517
+ let socket = this.secure ? this.connStream : this.stream;
518
+ return (socket.remoteAddress + ":" + socket.remotePort);
519
+ }
520
+ default:
521
+ errors.throwErr(errors.ERR_INTERNAL, "getOption not supported for opcode " + opcode);
522
+ }
523
+ }
524
+
525
+ }
526
+
527
+ module.exports = NTTCP;