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