From e60baaef11af6bcd6e7aee73b9e304732bf9a16e Mon Sep 17 00:00:00 2001
From: Chris Ridd <chris.ridd@forgerock.com>
Date: Fri, 23 May 2014 15:13:23 +0000
Subject: [PATCH] Backport fix for OPENDJ-1466: Improve initialization of InetSocketAddress in SDK to prevent cached DNS data.
---
opendj-ldap-sdk/src/test/java/org/forgerock/opendj/ldap/ConnectionFactoryTestCase.java | 85 +++++++++++++++++++---------
opendj-ldap-sdk/src/main/java/com/forgerock/opendj/ldap/LDAPConnectionFactoryImpl.java | 51 ++++++++++++++--
opendj-ldap-sdk/src/main/java/org/forgerock/opendj/ldap/LDAPConnectionFactory.java | 8 ++
3 files changed, 107 insertions(+), 37 deletions(-)
diff --git a/opendj-ldap-sdk/src/main/java/com/forgerock/opendj/ldap/LDAPConnectionFactoryImpl.java b/opendj-ldap-sdk/src/main/java/com/forgerock/opendj/ldap/LDAPConnectionFactoryImpl.java
index 2f397d2..56a5a99 100644
--- a/opendj-ldap-sdk/src/main/java/com/forgerock/opendj/ldap/LDAPConnectionFactoryImpl.java
+++ b/opendj-ldap-sdk/src/main/java/com/forgerock/opendj/ldap/LDAPConnectionFactoryImpl.java
@@ -211,8 +211,8 @@
return timeoutEndTime - currentTime;
} else {
future.handleErrorResult(newErrorResult(ResultCode.CLIENT_SIDE_CONNECT_ERROR,
- LDAP_CONNECTION_CONNECT_TIMEOUT.get(socketAddress.toString(), getTimeout())
- .toString()));
+ LDAP_CONNECTION_CONNECT_TIMEOUT.get(getSocketAddress().toString(),
+ getTimeout()).toString()));
return 0;
}
}
@@ -227,6 +227,8 @@
private final FilterChain defaultFilterChain;
private final LDAPOptions options;
private final InetSocketAddress socketAddress;
+ private final String host;
+ private final int port;
/**
* Prevents the transport and timeoutChecker being released when there are
@@ -246,8 +248,8 @@
/**
* Creates a new LDAP connection factory implementation which can be used to
- * create connections to the Directory Server at the provided host and port
- * address using provided connection options.
+ * create connections to the Directory Server at the provided address using
+ * provided connection options.
*
* @param address
* The address of the Directory Server to connect to.
@@ -257,6 +259,8 @@
public LDAPConnectionFactoryImpl(final InetSocketAddress address, final LDAPOptions options) {
this.transport = DEFAULT_TRANSPORT.acquireIfNull(options.getTCPNIOTransport());
this.socketAddress = address;
+ this.host = null;
+ this.port = -1;
this.options = new LDAPOptions(options);
this.clientFilter =
new LDAPClientFilter(new LDAPReader(this.options.getDecodeOptions()), 0);
@@ -264,6 +268,30 @@
FilterChainBuilder.stateless().add(new TransportFilter()).add(clientFilter).build();
}
+ /**
+ * Creates a new LDAP connection factory implementation which can be used to
+ * create connections to the Directory Server at the provided host and port
+ * number using provided connection options.
+ *
+ * @param host
+ * The host name of the Directory Server to connect to.
+ * @param port
+ * The port number of the Directory Server to connect to.
+ * @param options
+ * The LDAP connection options to use when creating connections.
+ */
+ public LDAPConnectionFactoryImpl(final String host, final int port, final LDAPOptions options) {
+ this.transport = DEFAULT_TRANSPORT.acquireIfNull(options.getTCPNIOTransport());
+ this.socketAddress = null;
+ this.host = host;
+ this.port = port;
+ this.options = new LDAPOptions(options);
+ this.clientFilter =
+ new LDAPClientFilter(new LDAPReader(this.options.getDecodeOptions()), 0);
+ this.defaultFilterChain =
+ FilterChainBuilder.stateless().add(new TransportFilter()).add(clientFilter).build();
+ }
+
@Override
public void close() {
if (isClosed.compareAndSet(false, true)) {
@@ -289,7 +317,7 @@
.build();
final AsynchronousFutureResult<Connection, ResultHandler<? super Connection>> future =
new AsynchronousFutureResult<Connection, ResultHandler<? super Connection>>(handler);
- connectorHandler.connect(socketAddress, new CompletionHandlerAdapter(future));
+ connectorHandler.connect(getSocketAddress(), new CompletionHandlerAdapter(future));
return future;
}
@@ -299,14 +327,23 @@
* @return The address of the Directory Server.
*/
public InetSocketAddress getSocketAddress() {
- return socketAddress;
+ if (socketAddress != null) {
+ return socketAddress;
+ }
+ return new InetSocketAddress(host, port);
}
@Override
public String toString() {
final StringBuilder builder = new StringBuilder();
builder.append("LDAPConnectionFactory(");
- builder.append(getSocketAddress().toString());
+ if (socketAddress != null) {
+ builder.append(socketAddress.toString());
+ } else {
+ builder.append(host);
+ builder.append(':');
+ builder.append(port);
+ }
builder.append(')');
return builder.toString();
}
diff --git a/opendj-ldap-sdk/src/main/java/org/forgerock/opendj/ldap/LDAPConnectionFactory.java b/opendj-ldap-sdk/src/main/java/org/forgerock/opendj/ldap/LDAPConnectionFactory.java
index 08eb75e..cbd9eb9 100644
--- a/opendj-ldap-sdk/src/main/java/org/forgerock/opendj/ldap/LDAPConnectionFactory.java
+++ b/opendj-ldap-sdk/src/main/java/org/forgerock/opendj/ldap/LDAPConnectionFactory.java
@@ -86,7 +86,9 @@
* The address of the Directory Server.
* @throws NullPointerException
* If {@code address} was {@code null}.
+ * @deprecated use {@link #LDAPConnectionFactory(String, int)} instead.
*/
+ @Deprecated
public LDAPConnectionFactory(final InetSocketAddress address) {
this(address, new LDAPOptions());
}
@@ -101,7 +103,10 @@
* The LDAP options to use when creating connections.
* @throws NullPointerException
* If {@code address} or {@code options} was {@code null}.
+ * @deprecated use {@link #LDAPConnectionFactory(String, int,
+ * org.forgerock.opendj.ldap.LDAPOptions)} instead.
*/
+ @Deprecated
public LDAPConnectionFactory(final InetSocketAddress address, final LDAPOptions options) {
Validator.ensureNotNull(address, options);
this.impl = new LDAPConnectionFactoryImpl(address, options);
@@ -139,8 +144,7 @@
*/
public LDAPConnectionFactory(final String host, final int port, final LDAPOptions options) {
Validator.ensureNotNull(host, options);
- final InetSocketAddress address = new InetSocketAddress(host, port);
- this.impl = new LDAPConnectionFactoryImpl(address, options);
+ this.impl = new LDAPConnectionFactoryImpl(host, port, options);
}
/**
diff --git a/opendj-ldap-sdk/src/test/java/org/forgerock/opendj/ldap/ConnectionFactoryTestCase.java b/opendj-ldap-sdk/src/test/java/org/forgerock/opendj/ldap/ConnectionFactoryTestCase.java
index bc49974..fc7ffff 100644
--- a/opendj-ldap-sdk/src/test/java/org/forgerock/opendj/ldap/ConnectionFactoryTestCase.java
+++ b/opendj-ldap-sdk/src/test/java/org/forgerock/opendj/ldap/ConnectionFactoryTestCase.java
@@ -22,7 +22,7 @@
*
*
* Copyright 2010 Sun Microsystems, Inc.
- * Portions copyright 2011-2013 ForgeRock AS
+ * Portions copyright 2011-2014 ForgeRock AS
*/
package org.forgerock.opendj.ldap;
@@ -43,6 +43,8 @@
import static org.testng.Assert.assertNotNull;
import static org.testng.Assert.assertTrue;
+import java.net.InetSocketAddress;
+import java.net.SocketAddress;
import java.util.Arrays;
import java.util.concurrent.Callable;
import java.util.concurrent.CountDownLatch;
@@ -133,7 +135,7 @@
@DataProvider
Object[][] connectionFactories() throws Exception {
- Object[][] factories = new Object[21][1];
+ Object[][] factories = new Object[27][1];
// HeartBeatConnectionFactory
// Use custom search request.
@@ -141,26 +143,45 @@
Requests.newSearchRequest("uid=user.0,ou=people,o=test", SearchScope.BASE_OBJECT,
"objectclass=*", "cn");
+ SocketAddress addr = getServerSocketAddress();
+ assertTrue(addr instanceof InetSocketAddress);
+ InetSocketAddress socketAddress = (InetSocketAddress) addr;
+
factories[0][0] =
Connections.newHeartBeatConnectionFactory(new LDAPConnectionFactory(
- getServerSocketAddress()), 1000, 500, TimeUnit.MILLISECONDS, request);
+ socketAddress), 1000, 500, TimeUnit.MILLISECONDS, request);
+ factories[1][0] =
+ Connections.newHeartBeatConnectionFactory(new LDAPConnectionFactory(
+ socketAddress.getHostName(), socketAddress.getPort()), 1000, 500,
+ TimeUnit.MILLISECONDS, request);
// InternalConnectionFactory
- factories[1][0] = Connections.newInternalConnectionFactory(LDAPServer.getInstance(), null);
+ factories[2][0] = Connections.newInternalConnectionFactory(LDAPServer.getInstance(), null);
// AuthenticatedConnectionFactory
- factories[2][0] =
- new AuthenticatedConnectionFactory(new LDAPConnectionFactory(
- getServerSocketAddress()), Requests.newSimpleBindRequest("", new char[0]));
-
- // AuthenticatedConnectionFactory with multi-stage SASL
factories[3][0] =
new AuthenticatedConnectionFactory(new LDAPConnectionFactory(
- getServerSocketAddress()), Requests.newCRAMMD5SASLBindRequest("id:user",
+ socketAddress), Requests.newSimpleBindRequest("", new char[0]));
+ factories[4][0] =
+ new AuthenticatedConnectionFactory(new LDAPConnectionFactory(
+ socketAddress.getHostName(), socketAddress.getPort()),
+ Requests.newSimpleBindRequest("", new char[0]));
+
+ // AuthenticatedConnectionFactory with multi-stage SASL
+ factories[5][0] =
+ new AuthenticatedConnectionFactory(new LDAPConnectionFactory(
+ socketAddress), Requests.newCRAMMD5SASLBindRequest("id:user",
+ "password".toCharArray()));
+ factories[6][0] =
+ new AuthenticatedConnectionFactory(new LDAPConnectionFactory(
+ socketAddress.getHostName(), socketAddress.getPort()),
+ Requests.newCRAMMD5SASLBindRequest("id:user",
"password".toCharArray()));
// LDAPConnectionFactory with default options
- factories[4][0] = new LDAPConnectionFactory(getServerSocketAddress());
+ factories[7][0] = new LDAPConnectionFactory(socketAddress);
+ factories[8][0] = new LDAPConnectionFactory(socketAddress.getHostName(),
+ socketAddress.getPort());
// LDAPConnectionFactory with startTLS
SSLContext sslContext =
@@ -174,16 +195,24 @@
"SSL_DH_anon_WITH_DES_CBC_SHA", "SSL_DH_anon_WITH_RC4_128_MD5",
"TLS_DH_anon_WITH_AES_128_CBC_SHA",
"TLS_DH_anon_WITH_AES_256_CBC_SHA" });
- factories[5][0] = new LDAPConnectionFactory(getServerSocketAddress(), options);
+ factories[9][0] = new LDAPConnectionFactory(socketAddress, options);
+ factories[10][0] = new LDAPConnectionFactory(socketAddress.getHostName(),
+ socketAddress.getPort(), options);
// startTLS + SASL confidentiality
// Use IP address here so that DIGEST-MD5 host verification works if
// local host name is not localhost (e.g. on some machines it might be
// localhost.localdomain).
// FIXME: enable QOP once OPENDJ-514 is fixed.
- factories[6][0] =
+ factories[11][0] =
new AuthenticatedConnectionFactory(new LDAPConnectionFactory(
- getServerSocketAddress(), options), Requests.newDigestMD5SASLBindRequest(
+ socketAddress, options), Requests.newDigestMD5SASLBindRequest(
+ "id:user", "password".toCharArray()).setCipher(
+ DigestMD5SASLBindRequest.CIPHER_LOW));
+ factories[12][0] =
+ new AuthenticatedConnectionFactory(new LDAPConnectionFactory(
+ socketAddress.getHostName(), socketAddress.getPort(), options),
+ Requests.newDigestMD5SASLBindRequest(
"id:user", "password".toCharArray()).setCipher(
DigestMD5SASLBindRequest.CIPHER_LOW));
@@ -197,45 +226,45 @@
getServerSocketAddress()), "online");
// Connection pools.
- factories[7][0] = Connections.newFixedConnectionPool(onlineServer, 10);
+ factories[13][0] = Connections.newFixedConnectionPool(onlineServer, 10);
// Round robin.
- factories[8][0] =
+ factories[14][0] =
Connections.newLoadBalancer(new RoundRobinLoadBalancingAlgorithm(Arrays.asList(
onlineServer, offlineServer1)));
- factories[9][0] = factories[8][0];
- factories[10][0] = factories[8][0];
- factories[11][0] =
+ factories[15][0] = factories[14][0];
+ factories[16][0] = factories[14][0];
+ factories[17][0] =
Connections.newLoadBalancer(new RoundRobinLoadBalancingAlgorithm(Arrays.asList(
offlineServer1, onlineServer)));
- factories[12][0] =
+ factories[18][0] =
Connections.newLoadBalancer(new RoundRobinLoadBalancingAlgorithm(Arrays.asList(
offlineServer1, offlineServer2, onlineServer)));
- factories[13][0] =
+ factories[19][0] =
Connections.newLoadBalancer(new RoundRobinLoadBalancingAlgorithm(Arrays
.<ConnectionFactory> asList(Connections.newFixedConnectionPool(
offlineServer1, 10), Connections.newFixedConnectionPool(
onlineServer, 10))));
// Fail-over.
- factories[14][0] =
+ factories[20][0] =
Connections.newLoadBalancer(new FailoverLoadBalancingAlgorithm(Arrays.asList(
onlineServer, offlineServer1)));
- factories[15][0] = factories[14][0];
- factories[16][0] = factories[14][0];
- factories[17][0] =
+ factories[21][0] = factories[20][0];
+ factories[22][0] = factories[20][0];
+ factories[23][0] =
Connections.newLoadBalancer(new FailoverLoadBalancingAlgorithm(Arrays.asList(
offlineServer1, onlineServer)));
- factories[18][0] =
+ factories[24][0] =
Connections.newLoadBalancer(new FailoverLoadBalancingAlgorithm(Arrays.asList(
offlineServer1, offlineServer2, onlineServer)));
- factories[19][0] =
+ factories[25][0] =
Connections.newLoadBalancer(new FailoverLoadBalancingAlgorithm(Arrays
.<ConnectionFactory> asList(Connections.newFixedConnectionPool(
offlineServer1, 10), Connections.newFixedConnectionPool(
onlineServer, 10))));
- factories[20][0] = Connections.newFixedConnectionPool(onlineServer, 10);
+ factories[26][0] = Connections.newFixedConnectionPool(onlineServer, 10);
return factories;
}
--
Gitblit v1.10.0