Skip to content

Commit 97abfbc

Browse files
committed
Network code enhancements in Thin mode
1 parent a3faee5 commit 97abfbc

File tree

5 files changed

+78
-143
lines changed

5 files changed

+78
-143
lines changed

lib/errors.js

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -145,7 +145,7 @@ const ERR_TLS_HOSTMATCH_FAILURE = 508;
145145
const ERR_INVALID_PACKET = 509;
146146
const ERR_CONNECTION_TIMEDOUT = 510;
147147
const ERR_CONNECTION_REFUSED = 511;
148-
const ERR_INVALID_ADDRESS = 512;
148+
const ERR_INVALID_CONNECTSTRING_PARAMETERS = 512;
149149
const ERR_CONNECTION_INBAND = 513;
150150
const ERR_INVALID_CONNECT_STRING_SYNTAX = 514;
151151
const ERR_INVALID_EZCONNECT_SYNTAX = 515;
@@ -406,8 +406,8 @@ messages.set(ERR_CONNECTION_TIMEDOUT, // NJS-510
406406
'connection to host %s port %d timed out. Request exceeded "%s" of %d seconds. (CONNECTION_ID=%s)');
407407
messages.set(ERR_CONNECTION_REFUSED, // NJS-511
408408
'connection to listener at host %s port %d was refused. (CONNECTION_ID=%s)\nCause: %s');
409-
messages.set(ERR_INVALID_ADDRESS, // NJS-512
410-
'invalid address specified. %s %s');
409+
messages.set(ERR_INVALID_CONNECTSTRING_PARAMETERS, // NJS-512
410+
'invalid connection string parameters.\n%s');
411411
messages.set(ERR_CONNECTION_INBAND, // NJS-513
412412
'error received through in-band notification: %s');
413413
messages.set(ERR_INVALID_CONNECT_STRING_SYNTAX, // NJS-514
@@ -701,7 +701,7 @@ module.exports = {
701701
ERR_INVALID_PACKET,
702702
ERR_CONNECTION_TIMEDOUT,
703703
ERR_CONNECTION_REFUSED,
704-
ERR_INVALID_ADDRESS,
704+
ERR_INVALID_CONNECTSTRING_PARAMETERS,
705705
ERR_CONNECTION_INBAND,
706706
ERR_INVALID_CONNECT_STRING_SYNTAX,
707707
ERR_INVALID_EZCONNECT_SYNTAX,

lib/thin/sqlnet/ezConnectResolver.js

Lines changed: 58 additions & 112 deletions
Original file line numberDiff line numberDiff line change
@@ -29,41 +29,6 @@
2929
const {lookup} = require('dns').promises;
3030
const errors = require("../../errors.js");
3131

32-
String.prototype.format = function() {
33-
var args = arguments;
34-
return this.replace(/{([0-9]+)}/g, function(match, index) {
35-
// check if the argument is there
36-
return typeof args[index] == 'undefined' ? match : args[index];
37-
});
38-
};
39-
40-
// String formats for creating the TNS URL.
41-
const DESCRIPTION_FORMAT = "(DESCRIPTION={0}{1}{2}{3})";
42-
const DESCRIPTION_FORMAT_LB = "(DESCRIPTION=(LOAD_BALANCE=ON){0}{1}{2}{3})";
43-
const ADDRESS_LIST_FORMAT = "(ADDRESS_LIST={0})";
44-
const ADDRESS_LIST_FORMAT_LB = "(ADDRESS_LIST=(LOAD_BALANCE=ON){0})";
45-
const ADDRESS_FORMAT = "(ADDRESS=(PROTOCOL={0})(HOST={1})(PORT={2}){3})";
46-
const HTTPS_PROXY_FORMAT = "(HTTPS_PROXY={0})";
47-
const HTTPS_PROXY_PORT_FORMAT = "(HTTPS_PROXY_PORT={0})";
48-
const CONNECT_DATA_FORMAT = "(CONNECT_DATA={0}{1}{2}{3}{4}{5}{6})";
49-
const SERVICE_NAME_FORMAT = "(SERVICE_NAME={0})";
50-
const SERVER_MODE_FORMAT = "(SERVER={0})";
51-
const INSTANCE_NAME_FORMAT = "(INSTANCE_NAME={0})";
52-
const SERVICE_TAG_FORMAT = "(SERVICE_TAG={0})";
53-
const POOL_CONNECTION_CLASS_FORMAT = "(POOL_CONNECTION_CLASS={0})";
54-
const POOL_PURITY_FORMAT = "(POOL_PURITY={0})";
55-
const CONNECTION_ID_PREFIX_FORMAT = "(CONNECTION_ID_PREFIX={0})";
56-
const SECURITY_FORMAT = "(SECURITY={0})";
57-
const SERVER_DN_MATCH_FORMAT = "(SSL_SERVER_DN_MATCH={0})";
58-
const SERVER_DN_FORMAT = "(SSL_SERVER_CERT_DN={0})";
59-
const MY_WALLET_DIR_FORMAT = "(MY_WALLET_DIRECTORY={0})";
60-
const ENCRYPTION_CLIENT_FORMAT = "(ENCRYPTION_CLIENT={0})";
61-
const ENCRYPTION_TYPES_CLIENT_FORMAT = "(ENCRYPTION_TYPES_CLIENT={0})";
62-
const CRYPTO_CHECKSUM_CLIENT_FORMAT = "(CRYPTO_CHECKSUM_CLIENT={0})";
63-
const CRYPTO_CHECKSUM_TYPES_CLIENT_FORMAT = "(CRYPTO_CHECKSUM_TYPES_CLIENT={0})";
64-
const KEY_VALUE_FORMAT = "({0}={1})";
65-
66-
6732
// The host information pattern of the EZConnect URL format.
6833
/*
6934
Used (?=) for lookahead and \\k<hostnames> for the backreference.Lookahead
@@ -183,24 +148,23 @@ class EZConnectResolver {
183148
}
184149

185150
// Try to get the proxy information from URL properties
186-
let proxyHost = this.urlProps.get("HTTPS_PROXY");
187-
let proxyPort = this.urlProps.get("HTTPS_PROXY_PORT");
188-
let addressInfo =
151+
const proxyHost = this.urlProps.get("HTTPS_PROXY");
152+
const proxyPort = this.urlProps.get("HTTPS_PROXY_PORT");
153+
const addressInfo =
189154
await this.buildAddressList(hostInfo, protocol, proxyHost, proxyPort);
190155

191156
let connectionIdPrefix =
192157
this.urlProps.get("CONNECTION_ID_PREFIX");
193158
// Build the available information in TNS format.
194-
if (this.lb) {
195-
return DESCRIPTION_FORMAT_LB.format(this.buildDescriptionParams(), addressInfo,
196-
this.buildConnectData(serviceName, serverMode, instanceName,
197-
connectionIdPrefix), this.buildSecurityInfo(protocol));
198-
} else {
199-
return DESCRIPTION_FORMAT.format(this.buildDescriptionParams(), addressInfo,
200-
this.buildConnectData(serviceName, serverMode, instanceName,
201-
connectionIdPrefix), this.buildSecurityInfo(protocol));
202-
}
203-
159+
const parts = [];
160+
if (this.lb)
161+
parts.push("(LOAD_BALANCE=ON)");
162+
parts.push(this.buildDescriptionParams());
163+
parts.push(addressInfo);
164+
parts.push(this.buildConnectData(serviceName, serverMode, instanceName,
165+
connectionIdPrefix));
166+
parts.push(this.buildSecurityInfo(protocol));
167+
return `(DESCRIPTION=${parts.join('')})`;
204168
}
205169

206170
/**
@@ -211,23 +175,31 @@ class EZConnectResolver {
211175
* @param connectionIdPrefix prefix which will be appended to the connection id [optional].
212176
* @return CONNECT_DATA as string
213177
*/
214-
buildConnectData(serviceName,
215-
serverMode,
216-
instanceName,
217-
connectionIdPrefix) {
218-
219-
let poolConnectionClass = this.urlProps.get("POOL_CONNECTION_CLASS");
220-
let poolPurity = this.urlProps.get("POOL_PURITY");
221-
let serviceTag = this.urlProps.get("SERVICE_TAG");
222-
223-
return CONNECT_DATA_FORMAT.format(SERVICE_NAME_FORMAT.format(serviceName == null ? '' : serviceName),
224-
serverMode == null ? '' : SERVER_MODE_FORMAT.format(serverMode),
225-
instanceName == null ? '' : INSTANCE_NAME_FORMAT.format(instanceName),
226-
poolConnectionClass == null ? '' : POOL_CONNECTION_CLASS_FORMAT.format(poolConnectionClass),
227-
poolPurity == null ? '' : POOL_PURITY_FORMAT.format(POOL_PURITY_FORMAT),
228-
serviceTag == null ? '' : SERVICE_TAG_FORMAT.format(serviceTag),
229-
connectionIdPrefix == null ? '' : CONNECTION_ID_PREFIX_FORMAT.format(connectionIdPrefix));
178+
buildConnectData(serviceName, serverMode, instanceName, connectionIdPrefix) {
179+
const poolConnectionClass = this.urlProps.get("POOL_CONNECTION_CLASS");
180+
const poolPurity = this.urlProps.get("POOL_PURITY");
181+
const serviceTag = this.urlProps.get("SERVICE_TAG");
182+
183+
const parts = [];
184+
if (serviceName)
185+
parts.push(`(SERVICE_NAME=${serviceName})`);
186+
else
187+
parts.push('(SERVICE_NAME=)');
188+
if (serverMode)
189+
parts.push(`(SERVER=${serverMode})`);
190+
if (instanceName)
191+
parts.push(`(INSTANCE_NAME=${instanceName})`);
192+
if (poolConnectionClass)
193+
parts.push(`(POOL_CONNECTION_CLASS=${poolConnectionClass})`);
194+
if (poolPurity)
195+
parts.push(`(POOL_PURITY=${poolPurity})`);
196+
if (serviceTag)
197+
parts.push(`(SERVICE_TAG=${serviceTag})`);
198+
if (connectionIdPrefix)
199+
parts.push(`(CONNECTION_ID_PREFIX=${connectionIdPrefix})`);
200+
return `(CONNECT_DATA=${parts.join("")})`;
230201
}
202+
231203
/**
232204
* Builds the address information of the DESCRIPTION node with the given
233205
* information.
@@ -245,8 +217,7 @@ class EZConnectResolver {
245217
let builder = new Array();
246218
let proxyInfo = '';
247219
if (proxyHost != null && proxyPort != null) {
248-
// Builds the proxy information if it is available
249-
proxyInfo = HTTPS_PROXY_FORMAT.format(proxyHost) + HTTPS_PROXY_PORT_FORMAT.format(proxyPort);
220+
proxyInfo = `(HTTPS_PROXY=${proxyHost})(HTTPS_PROXY_PORT=${proxyPort})`;
250221
}
251222

252223
if (protocol == null) protocol = 'TCP';
@@ -269,13 +240,14 @@ class EZConnectResolver {
269240
}
270241
}
271242
naddr += addressNodeCount;
272-
if (addressLists.length > 1 && addressNodeCount > 1) {
273-
builder.push(ADDRESS_LIST_FORMAT_LB.format(addressListBuilder.join('')));
274-
} else if (addressLists.length > 1) {
275-
builder.push(ADDRESS_LIST_FORMAT.format(addressListBuilder.join('')));
276-
} else {
277-
builder.push(addressListBuilder.join(''));
278-
}
243+
const parts = [];
244+
if (addressLists.length > 1 && addressNodeCount > 1)
245+
parts.push('(LOAD_BALANCE=ON)');
246+
parts.push(addressListBuilder.join(''));
247+
if (addressLists.length > 1)
248+
builder.push(`(ADDRESS_LIST=${parts.join('')})`);
249+
else
250+
builder.push(parts.join(''));
279251
}
280252
if (naddr == 1) {
281253
shost = shost.trim();
@@ -309,15 +281,12 @@ class EZConnectResolver {
309281
* @param proxyInfo
310282
* @return addressInfo
311283
*/
312-
getAddrStr(hostName, port,
313-
protocol, proxyInfo) {
284+
getAddrStr(hostName, port, protocol, proxyInfo) {
314285
let host = hostName.trim();
315286
// If it is IPV6 format address then remove the enclosing '[' and ']'
316287
if (host.startsWith("[") && host.endsWith("]"))
317288
host = host.substring(1, host.length - 1);
318-
319-
return ADDRESS_FORMAT.format(protocol, host, port, proxyInfo);
320-
289+
return `(ADDRESS=(PROTOCOL=${protocol})(HOST=${host})(PORT=${port})${proxyInfo})`;
321290
}
322291
/**
323292
* Builds the parameters for the DESCRIPTION node using the parsed properties
@@ -330,7 +299,7 @@ class EZConnectResolver {
330299
let builder = new Array();
331300
this.urlProps.forEach(function(v, k) {
332301
if (DESCRIPTION_PARAMS.includes(k)) // Add only if it is a DESCRIPTION node parameter
333-
builder.push(KEY_VALUE_FORMAT.format(k, v));
302+
builder.push(`(${k}=${v})`);
334303
});
335304
return builder.join('');
336305
}
@@ -341,41 +310,22 @@ class EZConnectResolver {
341310
* @return security node of the description as string.
342311
*/
343312
buildSecurityInfo(protocol) {
344-
let securityInfo = new Array();
313+
const securityInfo = new Array();
345314
if (protocol != null && protocol.toLowerCase() == "tcps") {
346315
// In EZConnect format if the DN match is not specified the enable it
347316
// by default for TCPS protocol.
348-
let serverDNMatch = this.urlProps.get("SSL_SERVER_DN_MATCH");
349-
let serverCertDN = this.urlProps.get("SSL_SERVER_CERT_DN");
350-
let walletDir = this.urlProps.get("MY_WALLET_DIRECTORY");
351-
if (serverDNMatch != null && (serverDNMatch == "false" || serverDNMatch == "off" || serverDNMatch == "no")) {
352-
securityInfo.push(SERVER_DN_MATCH_FORMAT.format(serverDNMatch));
353-
} else {
354-
securityInfo.push(SERVER_DN_MATCH_FORMAT.format('TRUE'));
355-
}
317+
const serverDNMatch = this.urlProps.get("SSL_SERVER_DN_MATCH") || 'TRUE';
318+
const serverCertDN = this.urlProps.get("SSL_SERVER_CERT_DN");
319+
const walletDir = this.urlProps.get("MY_WALLET_DIRECTORY");
320+
securityInfo.push(`(SSL_SERVER_DN_MATCH=${serverDNMatch})`);
356321
if (serverCertDN != null)
357-
securityInfo.push(SERVER_DN_FORMAT.format(serverCertDN));
358-
322+
securityInfo.push(`(SSL_SERVER_CERT_DN=${serverCertDN}})`);
359323
if (walletDir != null)
360-
securityInfo.push(MY_WALLET_DIR_FORMAT.format(walletDir));
361-
362-
} else {
363-
let encryptionClient = this.urlProps.get("ENCRYPTION_CLIENT");
364-
let encryptionClientTypes = this.urlProps.get("ENCRYPTION_TYPES_CLIENT");
365-
let checksumClient = this.urlProps.get("CRYPTO_CHECKSUM_CLIENT");
366-
let checksumClientTypes = this.urlProps.get("CRYPTO_CHECKSUM_TYPES_CLIENT");
367-
if (encryptionClient != null)
368-
securityInfo.push(ENCRYPTION_CLIENT_FORMAT.format(encryptionClient));
369-
if (encryptionClientTypes != null)
370-
securityInfo.push(ENCRYPTION_TYPES_CLIENT_FORMAT.format(encryptionClientTypes));
371-
if (checksumClient != null)
372-
securityInfo.push(CRYPTO_CHECKSUM_CLIENT_FORMAT.format(checksumClient));
373-
if (checksumClientTypes != null)
374-
securityInfo.push(CRYPTO_CHECKSUM_TYPES_CLIENT_FORMAT.format(checksumClientTypes));
375-
324+
securityInfo.push(`(MY_WALLET_DIRECTORY=${walletDir})`);
376325
}
377-
return (securityInfo.length == 0) ?
378-
'' : SECURITY_FORMAT.format(securityInfo.join(''));
326+
if (securityInfo.length === 0)
327+
return '';
328+
return `(SECURITY=${securityInfo.join('')})`;
379329
}
380330

381331
/**
@@ -529,10 +479,6 @@ class EZConnectResolver {
529479
aliasMap.set("ssl_server_cert_dn", "SSL_SERVER_CERT_DN");
530480
aliasMap.set("ssl_server_dn_match", "SSL_SERVER_DN_MATCH");
531481
aliasMap.set("wallet_location", "MY_WALLET_DIRECTORY");
532-
aliasMap.set("encryption_client", "ENCRYPTION_CLIENT");
533-
aliasMap.set("encryption_types_client", "ENCRYPTION_TYPES_CLIENT");
534-
aliasMap.set("crypto_checksum_client", "CRYPTO_CHECKSUM_CLIENT");
535-
aliasMap.set("crypto_checksum_types_client", "CRYPTO_CHECKSUM_TYPES_CLIENT");
536482
aliasMap.set("pool_connection_class", "POOL_CONNECTION_CLASS");
537483
aliasMap.set("pool_purity", "POOL_PURITY");
538484
aliasMap.set("service_tag", "SERVICE_TAG");

lib/thin/sqlnet/navNodes.js

Lines changed: 2 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -81,8 +81,8 @@ class Address {
8181
if (hostnvp)
8282
this.host = hostnvp.atom;
8383

84-
if (protnvp == null) errors.throwErr(errors.ERR_INVALID_ADDRESS, "undefined", "protocol not supported");
85-
this.prot = protnvp.atom;
84+
if (protnvp)
85+
this.prot = protnvp.atom;
8686

8787
if (httpsProxyNVP)
8888
this.httpsProxy = httpsProxyNVP.atom;
@@ -307,10 +307,6 @@ class Description {
307307
this.params.walletLocation = tmpnv.atom;
308308
}
309309
}
310-
} else if (childnv.name.toUpperCase() == "WEBSOCK_URI") {
311-
this.params.websockUri = childnv.atom;
312-
} else if (childnv.name.toUpperCase() == "WEBSOCK_UNAME") {
313-
this.params.websockUname = childnv.atom;
314310
}
315311
}
316312
}
@@ -734,12 +730,6 @@ class NavDescription extends Description {
734730
if ('httpsProxy' in this.params) {
735731
cs.sBuf.push("(HTTPS_PROXY=" + this.params.httpsProxy + ")");
736732
}
737-
if ('websockUri' in this.params) {
738-
cs.sBuf.push("(WEBSOCK_URI=" + this.params.websockUri + ")");
739-
}
740-
if ('websockUname' in this.params) {
741-
cs.sBuf.push("(WEBSOCK_UNAME=" + this.params.websockUname + ")");
742-
}
743733
if (!this.failover) {
744734
cs.sBuf.push(NavSchemaObject.NFO);
745735
}

lib/thin/sqlnet/networkSession.js

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -145,7 +145,7 @@ class NetworkSession {
145145
this.sAtts = new SessionAtts(uuid);
146146
this.sAtts.setFrom(userConfig);
147147
this.sAtts.setFrom(address.desc.params); /* Resolve attributes from Connect String */
148-
await this.sAtts.prepare();
148+
await this.sAtts.prepare(address.protocol);
149149

150150
/* Insert Connection ID */
151151
let rootNVPair = createNVPair(address.CNdata.join(""));
@@ -164,11 +164,10 @@ class NetworkSession {
164164
* Make the transport level connection
165165
*/
166166
async transportConnect(address) {
167-
if (address.protocol.toUpperCase() == 'TCP' ||
168-
address.protocol.toUpperCase() == 'TCPS') {
167+
if (address.protocol && (address.protocol.toUpperCase() == 'TCP' || address.protocol.toUpperCase() == 'TCPS')) {
169168
this.ntAdapter = new NTTCP(this.sAtts.nt);
170169
} else {
171-
errors.throwErr(errors.ERR_INVALID_ADDRESS, address.protocol, "protocol not supported");
170+
errors.throwErr(errors.ERR_INVALID_CONNECTSTRING_PARAMETERS, address.protocol + " protocol not supported");
172171
}
173172
await this.ntAdapter.connect(address);
174173
this.ntAdapter.startRead();
@@ -318,7 +317,10 @@ class NetworkSession {
318317
if (err.message.startsWith('NJS-510')) {
319318
this.ntAdapter.connected = true; // Pretend as connected
320319
}
321-
this.ntAdapter.disconnect(constants.NSFIMM);
320+
if (this.ntAdapter) {
321+
this.ntAdapter.disconnect(constants.NSFIMM);
322+
this.ntAdapter = null;
323+
}
322324
connected = false;
323325
savedErr = err;
324326
try {
@@ -510,8 +512,11 @@ class NetworkSession {
510512
let address;
511513
try {
512514
address = await this.getAddress(addressNode, userConfig);
513-
} catch {
514-
errors.throwErr(errors.ERR_INVALID_ADDRESS, "Ensure the ADDRESS parameters have been entered correctly", "the most likely incorrect parameter is the host name");
515+
} catch (err) {
516+
if (err.message == "All options tried") /* Not even one valid Address */
517+
errors.throwErr(errors.ERR_INVALID_CONNECTSTRING_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_CONNECTSTRING_PARAMETERS, err.message);
515520
}
516521
await this.connect1(address, addressNode, userConfig);
517522
}

lib/thin/sqlnet/sessionAtts.js

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -103,12 +103,6 @@ class SessionAtts {
103103
if (typeof params.sslServerCertDN === 'string') {
104104
this.nt.sslServerCertDN = params.sslServerCertDN;
105105
}
106-
if (typeof params.websockUname === 'string') {
107-
this.nt.websockUname = params.websockUname;
108-
}
109-
if (typeof params.websockUri === 'string') {
110-
this.nt.websockUri = params.websockURI;
111-
}
112106
if (typeof params.enable === 'string' && params.enable.toUpperCase() == "BROKEN") {
113107
this.nt.enabledDCD = true;
114108
}
@@ -141,7 +135,7 @@ class SessionAtts {
141135
* Prepare attributes for connection, Generate Connection ID and read Wallet file
142136
*
143137
*/
144-
async prepare() {
138+
async prepare(protocol) {
145139
if (!this.uuid) {
146140
this.uuid = await genuuid();
147141
this.uuid = this.uuid.toString('base64');
@@ -153,7 +147,7 @@ class SessionAtts {
153147
}
154148
this.nt.connectionId = this.connectionId;
155149

156-
if (this.nt.walletFile) {
150+
if (protocol && (protocol.toUpperCase() == "TCPS" && this.nt.walletFile)) {
157151
this.nt.wallet = await this.readWalletFile();
158152
}
159153

0 commit comments

Comments
 (0)