You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@geode.apache.org by ud...@apache.org on 2016/07/22 00:20:07 UTC
[20/26] incubator-geode git commit: GEODE-420: Clean up of
SocketCreator code in tests. SocketCreatorFactory currently singleton,
to amend at later stage
http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/c5ed7a6c/geode-core/src/main/java/com/gemstone/gemfire/internal/SocketCreator.java
----------------------------------------------------------------------
diff --git a/geode-core/src/main/java/com/gemstone/gemfire/internal/SocketCreator.java b/geode-core/src/main/java/com/gemstone/gemfire/internal/SocketCreator.java
deleted file mode 100755
index fded3c3..0000000
--- a/geode-core/src/main/java/com/gemstone/gemfire/internal/SocketCreator.java
+++ /dev/null
@@ -1,1345 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.gemstone.gemfire.internal;
-
-import com.gemstone.gemfire.GemFireConfigException;
-import com.gemstone.gemfire.SystemConnectException;
-import com.gemstone.gemfire.SystemFailure;
-import com.gemstone.gemfire.admin.internal.InetAddressUtil;
-import com.gemstone.gemfire.cache.wan.GatewaySender;
-import com.gemstone.gemfire.cache.wan.GatewayTransportFilter;
-import com.gemstone.gemfire.distributed.ClientSocketFactory;
-import com.gemstone.gemfire.distributed.internal.DistributionConfig;
-import com.gemstone.gemfire.distributed.internal.DistributionConfigImpl;
-import com.gemstone.gemfire.distributed.internal.InternalDistributedSystem;
-import com.gemstone.gemfire.internal.GfeConsoleReaderFactory.GfeConsoleReader;
-import com.gemstone.gemfire.internal.cache.wan.TransportFilterServerSocket;
-import com.gemstone.gemfire.internal.cache.wan.TransportFilterSocketFactory;
-import com.gemstone.gemfire.internal.i18n.LocalizedStrings;
-import com.gemstone.gemfire.internal.logging.LogService;
-import com.gemstone.gemfire.internal.logging.log4j.LocalizedMessage;
-import com.gemstone.gemfire.internal.util.PasswordUtil;
-import org.apache.logging.log4j.Logger;
-
-import javax.naming.Context;
-import javax.naming.NamingEnumeration;
-import javax.naming.directory.Attribute;
-import javax.naming.directory.Attributes;
-import javax.naming.directory.DirContext;
-import javax.naming.directory.InitialDirContext;
-import javax.net.ServerSocketFactory;
-import javax.net.SocketFactory;
-import javax.net.ssl.*;
-import java.io.FileInputStream;
-import java.io.FileNotFoundException;
-import java.io.IOException;
-import java.net.*;
-import java.nio.channels.ServerSocketChannel;
-import java.security.*;
-import java.security.cert.Certificate;
-import java.security.cert.CertificateException;
-import java.security.cert.X509Certificate;
-import java.util.*;
-
-/**
- * Analyze configuration data (gemfire.properties) and configure sockets
- * accordingly for SSL.
- * <p>
- * gemfire.useSSL = (true|false) default false.<br/>
- * gemfire.ssl.debug = (true|false) default false.<br/>
- * gemfire.ssl.needClientAuth = (true|false) default true.<br/>
- * gemfire.ssl.protocols = <i>list of protocols</i><br/>
- * gemfire.ssl.ciphers = <i>list of cipher suites</i><br/>
- * <p>
- * The following may be included to configure the certificates used by the
- * Sun Provider.
- * <p>
- * javax.net.ssl.trustStore = <i>pathname</i><br/>
- * javax.net.ssl.trustStorePassword = <i>password</i><br/>
- * javax.net.ssl.keyStore = <i>pathname</i><br/>
- * javax.net.ssl.keyStorePassword = <i>password</i><br/>
- * <p>
- * Additional properties will be set as System properties to be available
- * as needed by other provider implementations.
- */
-public class SocketCreator {
-
- private static final Logger logger = LogService.getLogger();
-
- /** Optional system property to enable GemFire usage of link-local addresses */
- public static final String USE_LINK_LOCAL_ADDRESSES_PROPERTY =
- DistributionConfig.GEMFIRE_PREFIX + "net.useLinkLocalAddresses";
-
- /** True if GemFire should use link-local addresses */
- private static final boolean useLinkLocalAddresses =
- Boolean.getBoolean(USE_LINK_LOCAL_ADDRESSES_PROPERTY);
-
- /** we cache localHost to avoid bug #40619, access-violation in native code */
- private static final InetAddress localHost;
-
- /** all classes should use this variable to determine whether to use IPv4 or IPv6 addresses */
- private static boolean useIPv6Addresses = !Boolean.getBoolean("java.net.preferIPv4Stack") &&
- Boolean.getBoolean("java.net.preferIPv6Addresses");
-
- private static final Map<InetAddress, String> hostNames = new HashMap<>();
-
- /** flag to force always using DNS (regardless of the fact that these lookups can hang) */
- public static final boolean FORCE_DNS_USE = Boolean.getBoolean(DistributionConfig.GEMFIRE_PREFIX + "forceDnsUse");
-
- /** set this to false to inhibit host name lookup */
- public static volatile boolean resolve_dns = true;
-
- /** The default instance for use in GemFire socket creation */
- private static SocketCreator DEFAULT_INSTANCE = new SocketCreator();
-
- /**
- * Allow unlimited concurrent reads (uses of SocketCreator). Re-initializing
- * SocketCreator requires the write lock which will block out all reads until
- * it's done. If this causes performance loss, removal of ReadWriteLock
- * should only impact the Console or Admin APIs.
- */
- //private final ReadWriteLock rw = new ReentrantReadWriteLock();
-
- /** True if this SocketCreator has been initialized and is ready to use */
- private boolean ready = false;
-
- /** True if configured to use SSL */
- private boolean useSSL;
-
- /** True if configured to require client authentication */
- private boolean needClientAuth;
-
- /** Space-delimited list of SSL protocols to use, 'any' allows any */
- private String[] protocols;
-
- /** Space-delimited list of SSL ciphers to use, 'any' allows any */
- private String[] ciphers;
-
- /** Only print this SocketCreator's config once */
- private boolean configShown = false;
-
- /** context for SSL socket factories */
- private SSLContext sslContext;
-
- static {
- InetAddress lh = null;
- try {
- lh = InetAddress.getByAddress(InetAddress.getLocalHost().getAddress());
- if (lh.isLoopbackAddress()) {
- InetAddress ipv4Fallback = null;
- InetAddress ipv6Fallback = null;
- // try to find a non-loopback address
- Set myInterfaces = getMyAddresses();
- boolean preferIPv6 = SocketCreator.useIPv6Addresses;
- String lhName = null;
- for (Iterator<InetAddress> it = myInterfaces.iterator(); lhName == null && it.hasNext(); ) {
- InetAddress addr = it.next();
- if (addr.isLoopbackAddress() || addr.isAnyLocalAddress()) {
- break;
- }
- boolean ipv6 = addr instanceof Inet6Address;
- boolean ipv4 = addr instanceof Inet4Address;
- if ( (preferIPv6 && ipv6)
- || (!preferIPv6 && ipv4) ) {
- String addrName = reverseDNS(addr);
- if (lh.isLoopbackAddress()) {
- lh = addr;
- lhName = addrName;
- } else if (addrName != null) {
- lh = addr;
- lhName = addrName;
- }
- } else {
- if (preferIPv6 && ipv4 && ipv4Fallback == null) {
- ipv4Fallback = addr;
- } else if (!preferIPv6 && ipv6 && ipv6Fallback == null) {
- ipv6Fallback = addr;
- }
- }
- }
- // vanilla Ubuntu installations will have a usable IPv6 address when
- // running as a guest OS on an IPv6-enabled machine. We also look for
- // the alternative IPv4 configuration.
- if (lh.isLoopbackAddress()) {
- if (ipv4Fallback != null) {
- lh = ipv4Fallback;
- SocketCreator.useIPv6Addresses = false;
- } else if (ipv6Fallback != null) {
- lh = ipv6Fallback;
- SocketCreator.useIPv6Addresses = true;
- }
- }
- }
- } catch (UnknownHostException e) {
- }
- localHost = lh;
- }
-
- /** A factory used to create client <code>Sockets</code>. */
- private ClientSocketFactory clientSocketFactory;
-
- /**
- * Whether to enable TCP keep alive for sockets. This boolean is controlled by
- * the gemfire.setTcpKeepAlive java system property. If not set then GemFire
- * will enable keep-alive on server->client and p2p connections.
- */
- public static final boolean ENABLE_TCP_KEEP_ALIVE;
-
-
-
- static {
- // bug #49484 - customers want tcp/ip keep-alive turned on by default
- // to avoid dropped connections. It can be turned off by setting this
- // property to false
- String str = System.getProperty(DistributionConfig.GEMFIRE_PREFIX + "setTcpKeepAlive");
- if (str != null) {
- ENABLE_TCP_KEEP_ALIVE = Boolean.getBoolean(DistributionConfig.GEMFIRE_PREFIX + "setTcpKeepAlive");
- } else {
- ENABLE_TCP_KEEP_ALIVE = true;
- }
- }
-
- // -------------------------------------------------------------------------
- // Constructor
- // -------------------------------------------------------------------------
-
- /** Constructs new SocketCreator instance. */
- private SocketCreator() {}
-
- // -------------------------------------------------------------------------
- // Static instance accessors
- // -------------------------------------------------------------------------
-
- /**
- * Returns the default instance for use in GemFire socket creation.
- * <p>
- * If not already initialized, the default instance of SocketCreator will be
- * initialized using defaults in {@link
- * DistributionConfig}. If any
- * values are specified in System properties, those values will be used to
- * override the defaults.
- * <p>
- * Synchronizes on the DEFAULT_INSTANCE.
- */
- public static SocketCreator getDefaultInstance() {
- synchronized (DEFAULT_INSTANCE) {
- if (!DEFAULT_INSTANCE.ready) {
- DEFAULT_INSTANCE.initialize();
- }
- }
- return DEFAULT_INSTANCE;
- }
-
- /**
- * Returns the default instance for use in GemFire socket creation after
- * initializing it using the DistributionConfig.
- * <p>
- * This will reinitialize the SocketCreator if it was previously initialized.
- * <p>
- * Synchronizes on the DEFAULT_INSTANCE.
- */
- public static SocketCreator getDefaultInstance(DistributionConfig config) {
- synchronized (DEFAULT_INSTANCE) {
- DEFAULT_INSTANCE.initialize(config);
- }
- return DEFAULT_INSTANCE;
- }
-
- /**
- * Returns the default instance for use in GemFire socket creation after
- * initializing it using defaults in {@link
- * DistributionConfig}. If any
- * values are specified in the provided properties or in System properties,
- * those values will be used to override the defaults.
- * <p>
- * This will reinitialize the SocketCreator if it was previously initialized.
- * <p>
- * Call will synchronize on the DEFAULT_INSTANCE.
- */
- public static SocketCreator getDefaultInstance(Properties props) {
- return getDefaultInstance(new DistributionConfigImpl(props));
- }
-
- /**
- * Create and initialize a new non-default instance of SocketCreator.
- * <p>
- * Synchronizes on the new instance.
- *
- * @param useSSL true if ssl is to be enabled
- * @param needClientAuth true if client authentication is required
- * @param protocols space-delimited list of ssl protocols to use
- * @param ciphers space-delimited list of ssl ciphers to use
- * @param sysProps vendor properties to be set as System properties
- */
- public static SocketCreator createNonDefaultInstance(boolean useSSL,
- boolean needClientAuth,
- String protocols,
- String ciphers,
- Properties sysProps) {
- SocketCreator sc = new SocketCreator();
- synchronized (sc) {
- sc.initialize(useSSL, needClientAuth, readArray(protocols), readArray(ciphers), sysProps);
- }
- return sc;
- }
-
- /**
- * All GemFire code should use this method instead of
- * InetAddress.getLocalHost(). See bug #40619
- */
- public static InetAddress getLocalHost() throws UnknownHostException {
- if (localHost == null) {
- throw new UnknownHostException();
- }
- return localHost;
- }
-
- /** All classes should use this instead of relying on the JRE system property */
- public static boolean preferIPv6Addresses() {
- return SocketCreator.useIPv6Addresses;
- }
-
- /**
- * returns the host name for the given inet address, using a local cache
- * of names to avoid dns hits and duplicate strings
- */
- public static synchronized String getHostName(InetAddress addr) {
- String result = (String)hostNames.get(addr);
- if (result == null) {
- result = addr.getHostName();
- hostNames.put(addr, result);
- }
- return result;
- }
-
- /**
- * returns the host name for the given inet address, using a local cache
- * of names to avoid dns hits and duplicate strings
- */
- public static synchronized String getCanonicalHostName(InetAddress addr, String hostName) {
- String result = (String)hostNames.get(addr);
- if (result == null) {
- hostNames.put(addr, hostName);
- return hostName;
- }
- return result;
- }
-
- /**
- * Reset the hostNames caches
- */
- public static synchronized void resetHostNameCache() {
- hostNames.clear();
- }
-
- // -------------------------------------------------------------------------
- // Initializers (change SocketCreator state)
- // -------------------------------------------------------------------------
-
- /**
- * Initialize this SocketCreator.
- * <p>
- * Caller must synchronize on the SocketCreator instance.
- *
- * @param useSSL true if ssl is to be enabled
- * @param needClientAuth true if client authentication is required
- * @param protocols array of ssl protocols to use
- * @param ciphers array of ssl ciphers to use
- * @param props vendor properties passed in through gfsecurity.properties
- */
- @SuppressWarnings("hiding")
- private void initialize(boolean useSSL,
- boolean needClientAuth,
- String[] protocols,
- String[] ciphers,
- Properties props) {
- Assert.assertHoldsLock(this, true);
- try {
-// rw.writeLock().lockInterruptibly();
-// try {
- this.useSSL = useSSL;
- this.needClientAuth = needClientAuth;
-
- this.protocols = protocols;
- this.ciphers = ciphers;
-
- if (this == DEFAULT_INSTANCE) {
- // set p2p values...
- if (this.useSSL) {
- System.setProperty( "p2p.useSSL", "true" );
- System.setProperty( "p2p.oldIO", "true" );
- System.setProperty( "p2p.nodirectBuffers", "true" );
-
- try {
- if (sslContext == null) {
- sslContext = createAndConfigureSSLContext(protocols, props);
- SSLContext.setDefault(sslContext);
- }
- } catch (Exception e) {
- throw new GemFireConfigException("Error configuring GemFire ssl ",e);
- }
- }
- else {
- System.setProperty( "p2p.useSSL", "false" );
- }
- // make sure TCPConduit picks up p2p properties...
- com.gemstone.gemfire.internal.tcp.TCPConduit.init();
- } else if (this.useSSL && sslContext == null) {
- try {
- sslContext = createAndConfigureSSLContext(protocols, props);
- } catch (Exception e) {
- throw new GemFireConfigException("Error configuring GemFire ssl ",e);
- }
- }
-
- initializeClientSocketFactory();
- this.ready = true;
-// }
-// finally {
-// rw.writeLock().unlock();
-// }
- }
- catch (VirtualMachineError err) {
- SystemFailure.initiateFailure(err);
- // If this ever returns, rethrow the error. We're poisoned
- // now, so don't let this thread continue.
- throw err;
- }
- catch ( Error t ) {
- // Whenever you catch Error or Throwable, you must also
- // catch VirtualMachineError (see above). However, there is
- // _still_ a possibility that you are dealing with a cascading
- // error condition, so you also need to check to see if the JVM
- // is still usable:
- SystemFailure.checkFailure();
- t.printStackTrace();
- throw t;
- }
- catch ( RuntimeException re ) {
- re.printStackTrace();
- throw re;
- }
- }
-
- /**
- * Creates & configures the SSLContext when SSL is enabled.
- *
- * @param protocolNames
- * valid SSL protocols for this connection
- * @param props
- * vendor properties passed in through gfsecurity.properties
- * @return new SSLContext configured using the given protocols & properties
- *
- * @throws GeneralSecurityException
- * if security information can not be found
- * @throws IOException
- * if information can not be loaded
- */
- private SSLContext createAndConfigureSSLContext(String[] protocolNames, Properties props)
- throws GeneralSecurityException, IOException {
-
- SSLContext newSSLContext = getSSLContextInstance(protocolNames);
- KeyManager[] keyManagers = getKeyManagers(props);
- TrustManager[] trustManagers = getTrustManagers(props);
-
- newSSLContext.init(keyManagers, trustManagers, null /* use the default secure random*/);
- return newSSLContext;
- }
-
- /**
- * Used by CacheServerLauncher and SystemAdmin to read the properties from
- * console
- *
- * @param env
- * Map in which the properties are to be read from console.
- */
- public static void readSSLProperties(Map<String, String> env) {
- readSSLProperties(env, false);
- }
-
- /**
- * Used to read the properties from console. AgentLauncher calls this method
- * directly & ignores gemfire.properties. CacheServerLauncher and SystemAdmin
- * call this through {@link #readSSLProperties(Map)} and do NOT ignore
- * gemfire.properties.
- *
- * @param env
- * Map in which the properties are to be read from console.
- * @param ignoreGemFirePropsFile
- * if <code>false</code> existing gemfire.properties file is read, if
- * <code>true</code>, properties from gemfire.properties file are
- * ignored.
- */
- public static void readSSLProperties(Map<String, String> env,
- boolean ignoreGemFirePropsFile) {
- Properties props = new Properties();
- DistributionConfigImpl.loadGemFireProperties(props, ignoreGemFirePropsFile);
- for (Object entry : props.entrySet()) {
- Map.Entry<String, String> ent = (Map.Entry<String, String>)entry;
- // if the value of ssl props is empty, read them from console
- if (ent.getKey().startsWith(DistributionConfig.SSL_SYSTEM_PROPS_NAME)
- || ent.getKey().startsWith(DistributionConfig.SYS_PROP_NAME)) {
- String key = ent.getKey();
- if (key.startsWith(DistributionConfig.SYS_PROP_NAME)) {
- key = key.substring(DistributionConfig.SYS_PROP_NAME.length());
- }
- if (ent.getValue() == null || ent.getValue().trim().equals("")) {
- GfeConsoleReader consoleReader = GfeConsoleReaderFactory.getDefaultConsoleReader();
- if (!consoleReader.isSupported()) {
- throw new GemFireConfigException("SSL properties are empty, but a console is not available");
- }
- if (key.toLowerCase().contains("password")) {
- char[] password = consoleReader.readPassword("Please enter "+key+": ");
- env.put(key, PasswordUtil.encrypt(new String(password), false));
- } else {
- String val = consoleReader.readLine("Please enter "+key+": ");
- env.put(key, val);
- }
-
- }
- }
- }
- }
-
- private static SSLContext getSSLContextInstance(String[] protocols) {
- SSLContext c = null;
- if (protocols != null && protocols.length > 0) {
- for (String protocol : protocols) {
- if (!protocol.equals("any")) {
- try {
- c = SSLContext.getInstance(protocol);
- break;
- } catch (NoSuchAlgorithmException e) {
- // continue
- }
- }
- }
- }
- if (c != null) {
- return c;
- }
- // lookup known algorithms
- String[] knownAlgorithms = {"SSL", "SSLv2", "SSLv3", "TLS", "TLSv1", "TLSv1.1", "TLSv1.2"};
- for (String algo : knownAlgorithms) {
- try {
- c = SSLContext.getInstance(algo);
- break;
- } catch (NoSuchAlgorithmException e) {
- // continue
- }
- }
- return c;
- }
-
- private TrustManager[] getTrustManagers(Properties sysProps)
- throws KeyStoreException, NoSuchAlgorithmException, CertificateException, IOException {
- TrustManager[] trustManagers = null;
- String trustStoreType = sysProps.getProperty("javax.net.ssl.trustStoreType");
- GfeConsoleReader consoleReader = GfeConsoleReaderFactory.getDefaultConsoleReader();
- if (trustStoreType == null) {
- trustStoreType = System.getProperty("javax.net.ssl.trustStoreType", KeyStore.getDefaultType());
- } else if (trustStoreType.trim().equals("")) {
- //read from console, default on empty
- if (consoleReader.isSupported()) {
- trustStoreType = consoleReader.readLine("Please enter the trustStoreType (javax.net.ssl.trustStoreType) : ");
- }
- if (isEmpty(trustStoreType)) {
- trustStoreType = KeyStore.getDefaultType();
- }
- }
- KeyStore ts = KeyStore.getInstance(trustStoreType);
- String trustStorePath = System.getProperty("javax.net.ssl.trustStore");
- if (trustStorePath == null) {
- trustStorePath = sysProps.getProperty("javax.net.ssl.trustStore");
- }
- if (trustStorePath != null) {
- if (trustStorePath.trim().equals("")) {
- trustStorePath = System.getenv("javax.net.ssl.trustStore");
- //read from console
- if (isEmpty(trustStorePath) && consoleReader.isSupported()) {
- trustStorePath = consoleReader.readLine("Please enter the trustStore location (javax.net.ssl.trustStore) : ");
- }
- }
- FileInputStream fis = new FileInputStream(trustStorePath);
- String passwordString = System.getProperty("javax.net.ssl.trustStorePassword");
- if (passwordString == null) {
- passwordString = sysProps.getProperty("javax.net.ssl.trustStorePassword");
- }
- char [] password = null;
- if (passwordString != null) {
- if (passwordString.trim().equals("")) {
- String encryptedPass = System.getenv("javax.net.ssl.trustStorePassword");
- if (!isEmpty(encryptedPass)) {
- String toDecrypt = "encrypted(" + encryptedPass + ")";
- passwordString = PasswordUtil.decrypt(toDecrypt);
- password = passwordString.toCharArray();
- }
- //read from the console
- if (isEmpty(passwordString) && consoleReader.isSupported()) {
- password = consoleReader.readPassword("Please enter password for trustStore (javax.net.ssl.trustStorePassword) : ");
- }
- } else {
- password = passwordString.toCharArray();
- }
- }
- ts.load(fis, password);
-
- // default algorithm can be changed by setting property "ssl.TrustManagerFactory.algorithm" in security properties
- TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
- tmf.init(ts);
- trustManagers = tmf.getTrustManagers();
- // follow the security tip in java doc
- if (password != null) {
- java.util.Arrays.fill(password, ' ');
- }
- }
- return trustManagers;
- }
-
- private KeyManager[] getKeyManagers(Properties sysProps)
- throws KeyStoreException, FileNotFoundException, IOException,
- NoSuchAlgorithmException, CertificateException, UnrecoverableKeyException {
- KeyManager[] keyManagers = null;
- String keyStoreType = sysProps.getProperty("javax.net.ssl.keyStoreType");
- GfeConsoleReader consoleReader = GfeConsoleReaderFactory.getDefaultConsoleReader();
- if (keyStoreType == null) {
- keyStoreType = System.getProperty("javax.net.ssl.keyStoreType", KeyStore.getDefaultType());
- } else if (keyStoreType.trim().equals("")) {
- // read from console, default on empty
- if (consoleReader.isSupported()) {
- keyStoreType = consoleReader.readLine("Please enter the keyStoreType (javax.net.ssl.keyStoreType) : ");
- }
- if (isEmpty(keyStoreType)) {
- keyStoreType = KeyStore.getDefaultType();
- }
- }
- KeyStore ks = KeyStore.getInstance(keyStoreType);
- String keyStoreFilePath = sysProps.getProperty("javax.net.ssl.keyStore");
- if (keyStoreFilePath == null) {
- keyStoreFilePath = System.getProperty("javax.net.ssl.keyStore");
- }
- if (keyStoreFilePath != null) {
- if (keyStoreFilePath.trim().equals("")) {
- keyStoreFilePath = System.getenv("javax.net.ssl.keyStore");
- //read from console
- if (isEmpty(keyStoreFilePath) && consoleReader.isSupported()) {
- keyStoreFilePath = consoleReader.readLine("Please enter the keyStore location (javax.net.ssl.keyStore) : ");
- }
- if (isEmpty(keyStoreFilePath)) {
- keyStoreFilePath = System.getProperty("user.home") + System.getProperty("file.separator") + ".keystore";
- }
- }
- FileInputStream fis = null;
- fis = new FileInputStream(keyStoreFilePath);
- String passwordString = sysProps.getProperty("javax.net.ssl.keyStorePassword");
- if (passwordString == null) {
- passwordString = System.getProperty("javax.net.ssl.keyStorePassword");
- }
- char [] password = null;
- if (passwordString != null) {
- if (passwordString.trim().equals("")) {
- String encryptedPass = System.getenv("javax.net.ssl.keyStorePassword");
- if (!isEmpty(encryptedPass)) {
- String toDecrypt = "encrypted(" + encryptedPass + ")";
- passwordString = PasswordUtil.decrypt(toDecrypt);
- password = passwordString.toCharArray();
- }
- //read from the console
- if (isEmpty(passwordString) && consoleReader != null) {
- password = consoleReader.readPassword("Please enter password for keyStore (javax.net.ssl.keyStorePassword) : ");
- }
- } else {
- password = passwordString.toCharArray();
- }
- }
- ks.load(fis, password);
- // default algorithm can be changed by setting property "ssl.KeyManagerFactory.algorithm" in security properties
- KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
- kmf.init(ks, password);
- keyManagers = kmf.getKeyManagers();
- // follow the security tip in java doc
- if (password != null) {
- java.util.Arrays.fill(password, ' ');
- }
- }
- return keyManagers;
- }
-
- private boolean isEmpty(String string) {
- return (string == null || string.trim().equals(""));
- }
-
- /**
- * Perform initialization using defaults in {@link
- * DistributionConfig}. If any
- * values are specified in System properties, those values will be used to
- * override the defaults.
- * <p>
- * Caller must synchronize on the SocketCreator instance.
- */
- private void initialize() {
- initialize(new DistributionConfigImpl(new Properties()));
- }
-
- /**
- * Initialize this SocketCreator using the DistributionConfig.
- * <p>
- * Caller must synchronize on the SocketCreator instance.
- */
- private void initialize(DistributionConfig config) {
- DistributionConfig conf = config;
- if (conf == null) {
- conf = new DistributionConfigImpl(new Properties());
- }
-
- initialize(conf.getClusterSSLEnabled(),
- conf.getClusterSSLRequireAuthentication(),
- readArray(conf.getClusterSSLProtocols()),
- readArray(conf.getClusterSSLCiphers()),
- conf.getClusterSSLProperties());
- }
-
- // -------------------------------------------------------------------------
- // Public methods
- // -------------------------------------------------------------------------
-
- /** Returns true if this SocketCreator is configured to use SSL. */
- public boolean useSSL() {
- return this.useSSL;
- }
-
- /**
- * Return a ServerSocket possibly configured for SSL.
- * SSL configuration is left up to JSSE properties in java.security file.
- */
- public ServerSocket createServerSocket( int nport, int backlog ) throws IOException {
- return createServerSocket( nport, backlog, null );
- }
-
- public ServerSocket createServerSocket(int nport, int backlog,
- InetAddress bindAddr, List<GatewayTransportFilter> transportFilters,
- int socketBufferSize)
- throws IOException {
- if (transportFilters.isEmpty()) {
- return createServerSocket(nport, backlog, bindAddr, socketBufferSize);
- }
- else {
- printConfig();
- ServerSocket result = new TransportFilterServerSocket(transportFilters);
- result.setReuseAddress(true);
- // Set the receive buffer size before binding the socket so
- // that large buffers will be allocated on accepted sockets (see
- // java.net.ServerSocket.setReceiverBufferSize javadocs)
- result.setReceiveBufferSize(socketBufferSize);
- try {
- result.bind(new InetSocketAddress(bindAddr, nport), backlog);
- }
- catch (BindException e) {
- BindException throwMe = new BindException(
- LocalizedStrings.SocketCreator_FAILED_TO_CREATE_SERVER_SOCKET_ON_0_1
- .toLocalizedString(new Object[] { bindAddr,
- Integer.valueOf(nport) }));
- throwMe.initCause(e);
- throw throwMe;
- }
- return result;
- }
- }
-
- /**
- * Return a ServerSocket possibly configured for SSL.
- * SSL configuration is left up to JSSE properties in java.security file.
- */
- public ServerSocket createServerSocket( int nport, int backlog, InetAddress bindAddr ) throws IOException {
- return createServerSocket( nport, backlog, bindAddr, -1, useSSL);
- }
-
- public ServerSocket createServerSocket(int nport, int backlog,
- InetAddress bindAddr, int socketBufferSize)
- throws IOException {
- return createServerSocket(nport, backlog, bindAddr, socketBufferSize, useSSL);
- }
-
- private ServerSocket createServerSocket(int nport, int backlog,
- InetAddress bindAddr, int socketBufferSize, boolean sslConnection)
- throws IOException {
- // rw.readLock().lockInterruptibly();
-// try {
- printConfig();
- if ( sslConnection ) {
- if (this.sslContext == null) {
- throw new GemFireConfigException("SSL not configured correctly, Please look at previous error");
- }
- ServerSocketFactory ssf = this.sslContext.getServerSocketFactory();
- SSLServerSocket serverSocket = (SSLServerSocket)ssf.createServerSocket();
- serverSocket.setReuseAddress(true);
- // If necessary, set the receive buffer size before binding the socket so
- // that large buffers will be allocated on accepted sockets (see
- // java.net.ServerSocket.setReceiverBufferSize javadocs)
- if (socketBufferSize != -1) {
- serverSocket.setReceiveBufferSize(socketBufferSize);
- }
- serverSocket.bind(new InetSocketAddress(bindAddr, nport), backlog);
- finishServerSocket( serverSocket );
- return serverSocket;
- }
- else {
- //log.info("Opening server socket on " + nport, new Exception("SocketCreation"));
- ServerSocket result = new ServerSocket();
- result.setReuseAddress(true);
- // If necessary, set the receive buffer size before binding the socket so
- // that large buffers will be allocated on accepted sockets (see
- // java.net.ServerSocket.setReceiverBufferSize javadocs)
- if (socketBufferSize != -1) {
- result.setReceiveBufferSize(socketBufferSize);
- }
- try {
- result.bind(new InetSocketAddress(bindAddr, nport), backlog);
- }
- catch (BindException e) {
- BindException throwMe = new BindException(LocalizedStrings.SocketCreator_FAILED_TO_CREATE_SERVER_SOCKET_ON_0_1.toLocalizedString(new Object[] {bindAddr, Integer.valueOf(nport)}));
- throwMe.initCause(e);
- throw throwMe;
- }
- return result;
- }
-// }
-// finally {
-// rw.readLock().unlock();
-// }
- }
-
- /**
- * Creates or bind server socket to a random port selected
- * from tcp-port-range which is same as membership-port-range.
- * @param ba
- * @param backlog
- * @param isBindAddress
- * @param tcpBufferSize
- * @return Returns the new server socket.
- * @throws IOException
- */
- public ServerSocket createServerSocketUsingPortRange(InetAddress ba, int backlog,
- boolean isBindAddress, boolean useNIO, int tcpBufferSize, int[] tcpPortRange)
- throws IOException {
- return createServerSocketUsingPortRange(ba, backlog, isBindAddress, useNIO, tcpBufferSize, tcpPortRange, this.useSSL);
- }
-
- /**
- * Creates or bind server socket to a random port selected
- * from tcp-port-range which is same as membership-port-range.
- * @param ba
- * @param backlog
- * @param isBindAddress
- * @param tcpBufferSize
- * @param sslConnection whether to connect using SSL
- * @return Returns the new server socket.
- * @throws IOException
- */
- public ServerSocket createServerSocketUsingPortRange(InetAddress ba, int backlog,
- boolean isBindAddress, boolean useNIO, int tcpBufferSize, int[] tcpPortRange, boolean sslConnection)
- throws IOException {
- ServerSocket socket = null;
- int localPort = 0;
- int startingPort = 0;
-
- // Get a random port from range.
- Random rand = new SecureRandom();
- int portLimit = tcpPortRange[1];
- int randPort = tcpPortRange[0] + rand.nextInt(tcpPortRange[1] - tcpPortRange[0] + 1);
-
- startingPort = randPort;
- localPort = startingPort;
-
- while (true) {
- if (localPort > portLimit) {
- if (startingPort != 0) {
- localPort = tcpPortRange[0];
- portLimit = startingPort - 1;
- startingPort = 0;
- } else {
- throw new SystemConnectException(
- LocalizedStrings.TCPConduit_UNABLE_TO_FIND_FREE_PORT.toLocalizedString());
- }
- }
- try {
- if (useNIO) {
- ServerSocketChannel channl = ServerSocketChannel.open();
- socket = channl.socket();
-
- InetSocketAddress addr = new InetSocketAddress(isBindAddress ? ba : null, localPort);
- socket.bind(addr, backlog);
- } else {
- socket = SocketCreator.getDefaultInstance()
- .createServerSocket(localPort, backlog, isBindAddress? ba : null, tcpBufferSize, sslConnection);
- }
- break;
- } catch (java.net.SocketException ex) {
- if (useNIO || SocketCreator.treatAsBindException(ex)) {
- localPort++;
- } else {
- throw ex;
- }
- }
- }
- return socket;
- }
-
- public static boolean treatAsBindException(SocketException se) {
- if(se instanceof BindException) {
- return true;
- }
- final String msg = se.getMessage();
- return (msg != null && msg.contains("Invalid argument: listen failed"));
- }
-
- /** Return a client socket. This method is used by client/server clients. */
- public Socket connectForClient( String host, int port, int timeout ) throws IOException {
- return connect( InetAddress.getByName( host ), port, timeout, null, true, -1 );
- }
-
- /** Return a client socket. This method is used by client/server clients. */
- public Socket connectForClient( String host, int port, int timeout, int socketBufferSize ) throws IOException {
- return connect( InetAddress.getByName( host ), port, timeout, null, true, socketBufferSize );
- }
-
- /** Return a client socket. This method is used by peers. */
- public Socket connectForServer( InetAddress inetadd, int port ) throws IOException {
- return connect(inetadd, port, 0, null, false, -1);
- }
-
- /** Return a client socket. This method is used by peers. */
- public Socket connectForServer( InetAddress inetadd, int port, int socketBufferSize ) throws IOException {
- return connect(inetadd, port, 0, null, false, socketBufferSize);
- }
-
- /**
- * Return a client socket, timing out if unable to connect and timeout > 0 (millis).
- * The parameter <i>timeout</i> is ignored if SSL is being used, as there is no
- * timeout argument in the ssl socket factory
- */
- public Socket connect(InetAddress inetadd, int port, int timeout,
- ConnectionWatcher optionalWatcher, boolean clientSide)
- throws IOException {
- return connect(inetadd, port, timeout, optionalWatcher, clientSide, -1);
- }
-
- /**
- * Return a client socket, timing out if unable to connect and timeout > 0 (millis).
- * The parameter <i>timeout</i> is ignored if SSL is being used, as there is no
- * timeout argument in the ssl socket factory
- */
- public Socket connect(InetAddress inetadd, int port, int timeout,
- ConnectionWatcher optionalWatcher, boolean clientSide, int socketBufferSize) throws IOException {
- return connect(inetadd, port, timeout, optionalWatcher, clientSide, socketBufferSize, this.useSSL);
- }
-
- /**
- * Return a client socket, timing out if unable to connect and timeout > 0 (millis).
- * The parameter <i>timeout</i> is ignored if SSL is being used, as there is no
- * timeout argument in the ssl socket factory
- */
- public Socket connect(InetAddress inetadd, int port,
- int timeout, ConnectionWatcher optionalWatcher, boolean clientSide,
- int socketBufferSize, boolean sslConnection) throws IOException {
- Socket socket = null;
- SocketAddress sockaddr = new InetSocketAddress(inetadd, port);
- printConfig();
- try {
- if ( sslConnection ) {
- if (this.sslContext == null) {
- throw new GemFireConfigException("SSL not configured correctly, Please look at previous error");
- }
- SocketFactory sf = this.sslContext.getSocketFactory();
- socket = sf.createSocket();
-
- // Optionally enable SO_KEEPALIVE in the OS network protocol.
- socket.setKeepAlive(ENABLE_TCP_KEEP_ALIVE);
-
- // If necessary, set the receive buffer size before connecting the
- // socket so that large buffers will be allocated on accepted sockets
- // (see java.net.Socket.setReceiverBufferSize javadocs for details)
- if (socketBufferSize != -1) {
- socket.setReceiveBufferSize(socketBufferSize);
- }
-
- if (optionalWatcher != null) {
- optionalWatcher.beforeConnect(socket);
- }
- socket.connect(sockaddr, Math.max(timeout,0));
- configureClientSSLSocket( socket );
- return socket;
- }
- else {
- if (clientSide && this.clientSocketFactory != null) {
- socket = this.clientSocketFactory.createSocket( inetadd, port );
- } else {
- socket = new Socket( );
-
- // Optionally enable SO_KEEPALIVE in the OS network protocol.
- socket.setKeepAlive(ENABLE_TCP_KEEP_ALIVE);
-
- // If necessary, set the receive buffer size before connecting the
- // socket so that large buffers will be allocated on accepted sockets
- // (see java.net.Socket.setReceiverBufferSize javadocs for details)
- if (socketBufferSize != -1) {
- socket.setReceiveBufferSize(socketBufferSize);
- }
-
- if (optionalWatcher != null) {
- optionalWatcher.beforeConnect(socket);
- }
- socket.connect(sockaddr, Math.max(timeout,0));
- }
- return socket;
- }
- }
- finally {
- if (optionalWatcher != null) {
- optionalWatcher.afterConnect(socket);
- }
- }
-// }
-// finally {
-// rw.readLock().unlock();
-// }
- }
-
- /** Will be a server socket... this one simply registers the listeners. */
- public void configureServerSSLSocket( Socket socket ) throws IOException {
-// rw.readLock().lockInterruptibly();
-// try {
- if (socket instanceof SSLSocket) {
- SSLSocket sslSocket = (SSLSocket)socket;
- try {
- sslSocket.startHandshake();
- SSLSession session = sslSocket.getSession();
- Certificate[] peer = session.getPeerCertificates();
- if (logger.isDebugEnabled()) {
- logger.debug(LocalizedMessage.create(LocalizedStrings.SocketCreator_SSL_CONNECTION_FROM_PEER_0, ((X509Certificate)peer[0]).getSubjectDN()));
- }
- }
- catch (SSLPeerUnverifiedException ex) {
- if (this.needClientAuth) {
- logger.fatal(LocalizedMessage.create(LocalizedStrings.SocketCreator_SSL_ERROR_IN_AUTHENTICATING_PEER_0_1, new Object[] { socket.getInetAddress(), Integer.valueOf(socket.getPort())}), ex);
- throw ex;
- }
- }
- catch (SSLException ex) {
- logger.fatal(LocalizedMessage.create(LocalizedStrings.SocketCreator_SSL_ERROR_IN_CONNECTING_TO_PEER_0_1, new Object[] { socket.getInetAddress(), Integer.valueOf(socket.getPort())}), ex);
- throw ex;
- }
- } // ...if
-// }
-// finally {
-// rw.readLock().unlock();
-// }
- }
-
- // -------------------------------------------------------------------------
- // Private implementation methods
- // -------------------------------------------------------------------------
-
- /** Configure the SSLServerSocket based on this SocketCreator's settings. */
- private void finishServerSocket( SSLServerSocket serverSocket ) throws IOException {
- serverSocket.setUseClientMode( false );
- if ( this.needClientAuth ) {
- //serverSocket.setWantClientAuth( true );
- serverSocket.setNeedClientAuth( true );
- }
- serverSocket.setEnableSessionCreation( true );
-
- // restrict cyphers
- if ( ! "any".equalsIgnoreCase( this.protocols[0] ) ) {
- serverSocket.setEnabledProtocols( this.protocols );
- }
- if ( ! "any".equalsIgnoreCase( this.ciphers[0] ) ) {
- serverSocket.setEnabledCipherSuites( this.ciphers );
- }
- }
-
- /**
- * When a socket is accepted from a server socket, it should be passed to
- * this method for SSL configuration.
- */
- private void configureClientSSLSocket( Socket socket ) throws IOException {
- if ( socket instanceof SSLSocket ) {
- SSLSocket sslSocket = (SSLSocket) socket;
-
- sslSocket.setUseClientMode( true );
- sslSocket.setEnableSessionCreation( true );
-
- // restrict cyphers
- if ( this.protocols != null && !"any".equalsIgnoreCase(this.protocols[0]) ) {
- sslSocket.setEnabledProtocols( this.protocols );
- }
- if ( this.ciphers != null && !"any".equalsIgnoreCase(this.ciphers[0]) ) {
- sslSocket.setEnabledCipherSuites( this.ciphers );
- }
-
- try {
- sslSocket.startHandshake();
- SSLSession session = sslSocket.getSession();
- Certificate[] peer = session.getPeerCertificates();
- if (logger.isDebugEnabled()) {
- logger.debug(LocalizedMessage.create(LocalizedStrings.SocketCreator_SSL_CONNECTION_FROM_PEER_0, ((X509Certificate)peer[0]).getSubjectDN()));
- }
- }
- catch (SSLPeerUnverifiedException ex) {
- if (this.needClientAuth) {
- logger.fatal(LocalizedMessage.create(LocalizedStrings.SocketCreator_SSL_ERROR_IN_AUTHENTICATING_PEER), ex);
- throw ex;
- }
- }
- catch (SSLException ex) {
- logger.fatal(LocalizedMessage.create(LocalizedStrings.SocketCreator_SSL_ERROR_IN_CONNECTING_TO_PEER_0_1, new Object[] {socket.getInetAddress(), Integer.valueOf(socket.getPort())}), ex);
- throw ex;
- }
- // catch ( IOException e ) {
- // if ( this.needClientAuth ) {
- // logSevere( log, "SSL Error in authenticating peer.", e );
- // throw e;
- // }
- // else {
- // logWarning( log, "SSL Error in authenticating peer.", e );
- // }
- // }
- }
- }
-
- /** Print current configured state to log. */
- private void printConfig() {
- if ( ! configShown && logger.isDebugEnabled()) {
- configShown = true;
- StringBuffer sb = new StringBuffer();
- sb.append( "SSL Configuration: \n" );
- sb.append( " ssl-enabled = " + this.useSSL ).append( "\n" );
- // add other options here....
- for (String key: System.getProperties().stringPropertyNames()) { // fix for 46822
- if ( key.startsWith( "javax.net.ssl" ) ) {
- sb.append( " " ).append( key ).append( " = " ).append( System.getProperty( key ) ).append( "\n" );
- }
- }
- logger.debug( sb.toString() );
- }
- }
-
- /** Read an array of values from a string, whitespace separated. */
- private static String[] readArray( String text ) {
- if ( text == null || text.trim().equals( "" ) ) {
- return null;
- }
-
- StringTokenizer st = new StringTokenizer( text );
- Vector v = new Vector( );
- while( st.hasMoreTokens() ) {
- v.add( st.nextToken() );
- }
- return (String[]) v.toArray( new String[ v.size() ] );
- }
-
-
- protected void initializeClientSocketFactory() {
- this.clientSocketFactory = null;
- String className = System.getProperty(DistributionConfig.GEMFIRE_PREFIX + "clientSocketFactory");
- if (className != null) {
- Object o;
- try {
- Class c = ClassPathLoader.getLatest().forName(className);
- o = c.newInstance();
- }
- catch (Exception e) {
- // No cache exists yet, so this can't be logged.
- String s = "An unexpected exception occurred while instantiating a "
- + className + ": " + e;
- throw new IllegalArgumentException(s);
- }
- if (o instanceof ClientSocketFactory) {
- this.clientSocketFactory = (ClientSocketFactory) o;
- } else {
- String s = "Class \"" + className + "\" is not a ClientSocketFactory";
- throw new IllegalArgumentException(s);
- }
- }
- }
-
- public void initializeTransportFilterClientSocketFactory(GatewaySender sender) {
- this.clientSocketFactory = new TransportFilterSocketFactory()
- .setGatewayTransportFilters(sender.getGatewayTransportFilters());
- }
-
-// // -------------------------------------------------------------------------
-// // dummy ReadWriteLock impl's used to compare performance impact of
-// // WriterPreferenceReadWriteLock usage
-// // -------------------------------------------------------------------------
-
-// private class RW implements ReadWriteLock {
-// public Sync readLock() {
-// return new S();
-// }
-// public Sync writeLock() {
-// return new S();
-// }
-// }
-// private class S implements Sync {
-// public void acquire() throws InterruptedException {}
-// public boolean attempt(long msecs) throws InterruptedException { return true; }
-// public void release() {}
-// }
-
-
- /** returns a set of the non-loopback InetAddresses for this machine */
- public static Set<InetAddress> getMyAddresses() {
- Set<InetAddress> result = new HashSet<InetAddress>();
- Set<InetAddress> locals = new HashSet<InetAddress>();
- Enumeration<NetworkInterface> interfaces;
- try {
- interfaces = NetworkInterface.getNetworkInterfaces();
- } catch (SocketException e) {
- throw new IllegalArgumentException(
- LocalizedStrings.StartupMessage_UNABLE_TO_EXAMINE_NETWORK_INTERFACES
- .toLocalizedString(), e);
- }
- while (interfaces.hasMoreElements()) {
- NetworkInterface face = interfaces.nextElement();
- boolean faceIsUp = false;
- try {
- faceIsUp = face.isUp();
- } catch (SocketException e) {
- InternalDistributedSystem ids = InternalDistributedSystem.getAnyInstance();
- if (ids != null) {
- logger.info("Failed to check if network interface is up. Skipping {}", face, e);
- }
- }
- if (faceIsUp) {
- Enumeration<InetAddress> addrs = face.getInetAddresses();
- while (addrs.hasMoreElements()) {
- InetAddress addr = addrs.nextElement();
- if (addr.isLoopbackAddress() || addr.isAnyLocalAddress()
- || (!useLinkLocalAddresses && addr.isLinkLocalAddress())) {
- locals.add(addr);
- } else {
- result.add(addr);
- }
- } // while
- }
- } // while
- // fix for bug #42427 - allow product to run on a standalone box by using
- // local addresses if there are no non-local addresses available
- if (result.size() == 0) {
- return locals;
- } else {
- return result;
- }
- }
-
- /**
- * This method uses JNDI to look up an address in DNS and return its name
- * @param addr
- * @return the host name associated with the address or null if lookup isn't possible or there is no host name for this address
- */
- public static String reverseDNS(InetAddress addr) {
- byte[] addrBytes = addr.getAddress();
- // reverse the address suitable for reverse lookup
- String lookup = "";
- for (int index = addrBytes.length - 1; index >= 0; index--) {
- lookup = lookup + (addrBytes[index] & 0xff) + '.';
- }
- lookup += "in-addr.arpa";
-// System.out.println("Looking up: " + lookup);
-
- try {
- Hashtable env = new Hashtable();
- env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.dns.DnsContextFactory");
- DirContext ctx = new InitialDirContext(env);
- Attributes attrs = ctx.getAttributes(lookup, new String[] {"PTR"});
- for (NamingEnumeration ae = attrs.getAll();ae.hasMoreElements();) {
- Attribute attr = (Attribute)ae.next();
- for (Enumeration vals = attr.getAll();vals.hasMoreElements();) {
- Object elem = vals.nextElement();
- if ("PTR".equals(attr.getID()) && elem != null) {
- return elem.toString();
- }
- }
- }
- ctx.close();
- } catch(Exception e) {
- // ignored
- }
- return null;
- }
-
- /** Returns true if host matches the LOCALHOST. */
- public static boolean isLocalHost(Object host) {
- if (host instanceof InetAddress) {
- if (InetAddressUtil.LOCALHOST.equals(host)) {
- return true;
- }
- else if (((InetAddress) host).isLoopbackAddress()) {
- return true;
- }
- else {
- try {
- Enumeration en=NetworkInterface.getNetworkInterfaces();
- while(en.hasMoreElements()) {
- NetworkInterface i=(NetworkInterface)en.nextElement();
- for(Enumeration en2=i.getInetAddresses(); en2.hasMoreElements();) {
- InetAddress addr=(InetAddress)en2.nextElement();
- if (host.equals(addr)) {
- return true;
- }
- }
- }
- return false;
- }
- catch (SocketException e) {
- throw new IllegalArgumentException(LocalizedStrings.InetAddressUtil_UNABLE_TO_QUERY_NETWORK_INTERFACE.toLocalizedString(), e);
- }
- }
- }
- else {
- return isLocalHost(toInetAddress(host.toString()));
- }
- }
-
- /**
- * Converts the string host to an instance of InetAddress. Returns null if
- * the string is empty. Fails Assertion if the conversion would result in
- * <code>java.lang.UnknownHostException</code>.
- * <p>
- * Any leading slashes on host will be ignored.
- *
- * @param host string version the InetAddress
- * @return the host converted to InetAddress instance
- */
- public static InetAddress toInetAddress(String host) {
- if (host == null || host.length() == 0) {
- return null;
- }
- try {
- if (host.indexOf("/") > -1) {
- return InetAddress.getByName(host.substring(host.indexOf("/") + 1));
- }
- else {
- return InetAddress.getByName(host);
- }
- } catch (java.net.UnknownHostException e) {
- throw new IllegalArgumentException(e.getMessage());
- }
- }
-}
-
http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/c5ed7a6c/geode-core/src/main/java/com/gemstone/gemfire/internal/StatArchiveWriter.java
----------------------------------------------------------------------
diff --git a/geode-core/src/main/java/com/gemstone/gemfire/internal/StatArchiveWriter.java b/geode-core/src/main/java/com/gemstone/gemfire/internal/StatArchiveWriter.java
index fcf645d..9308e60 100644
--- a/geode-core/src/main/java/com/gemstone/gemfire/internal/StatArchiveWriter.java
+++ b/geode-core/src/main/java/com/gemstone/gemfire/internal/StatArchiveWriter.java
@@ -23,6 +23,7 @@ import com.gemstone.gemfire.distributed.internal.DistributionConfig;
import com.gemstone.gemfire.internal.i18n.LocalizedStrings;
import com.gemstone.gemfire.internal.logging.LogService;
import com.gemstone.gemfire.internal.logging.log4j.LogMarker;
+import com.gemstone.gemfire.internal.net.SocketCreator;
import com.gemstone.gemfire.internal.statistics.ResourceInstance;
import com.gemstone.gemfire.internal.statistics.ResourceType;
import com.gemstone.gemfire.internal.statistics.SampleHandler;
http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/c5ed7a6c/geode-core/src/main/java/com/gemstone/gemfire/internal/SystemAdmin.java
----------------------------------------------------------------------
diff --git a/geode-core/src/main/java/com/gemstone/gemfire/internal/SystemAdmin.java b/geode-core/src/main/java/com/gemstone/gemfire/internal/SystemAdmin.java
index cc03ad6..9b2806c 100644
--- a/geode-core/src/main/java/com/gemstone/gemfire/internal/SystemAdmin.java
+++ b/geode-core/src/main/java/com/gemstone/gemfire/internal/SystemAdmin.java
@@ -33,6 +33,7 @@ import com.gemstone.gemfire.internal.cache.DiskStoreImpl;
import com.gemstone.gemfire.internal.i18n.LocalizedStrings;
import com.gemstone.gemfire.internal.logging.DateFormatter;
import com.gemstone.gemfire.internal.logging.MergeLogFiles;
+import com.gemstone.gemfire.internal.net.SocketCreator;
import com.gemstone.gemfire.internal.util.JavaCommandBuilder;
import com.gemstone.gemfire.internal.util.PasswordUtil;
import com.gemstone.gemfire.internal.util.PluckStacks;
http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/c5ed7a6c/geode-core/src/main/java/com/gemstone/gemfire/internal/admin/remote/DistributionLocatorId.java
----------------------------------------------------------------------
diff --git a/geode-core/src/main/java/com/gemstone/gemfire/internal/admin/remote/DistributionLocatorId.java b/geode-core/src/main/java/com/gemstone/gemfire/internal/admin/remote/DistributionLocatorId.java
index 87fa715..85b84bd 100644
--- a/geode-core/src/main/java/com/gemstone/gemfire/internal/admin/remote/DistributionLocatorId.java
+++ b/geode-core/src/main/java/com/gemstone/gemfire/internal/admin/remote/DistributionLocatorId.java
@@ -20,7 +20,7 @@ package com.gemstone.gemfire.internal.admin.remote;
import com.gemstone.gemfire.InternalGemFireException;
import com.gemstone.gemfire.distributed.Locator;
import com.gemstone.gemfire.distributed.internal.DistributionConfig;
-import com.gemstone.gemfire.internal.SocketCreator;
+import com.gemstone.gemfire.internal.net.SocketCreator;
import com.gemstone.gemfire.internal.admin.SSLConfig;
import com.gemstone.gemfire.internal.i18n.LocalizedStrings;
http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/c5ed7a6c/geode-core/src/main/java/com/gemstone/gemfire/internal/admin/remote/FetchHostResponse.java
----------------------------------------------------------------------
diff --git a/geode-core/src/main/java/com/gemstone/gemfire/internal/admin/remote/FetchHostResponse.java b/geode-core/src/main/java/com/gemstone/gemfire/internal/admin/remote/FetchHostResponse.java
index a9712be..ddf37f7 100644
--- a/geode-core/src/main/java/com/gemstone/gemfire/internal/admin/remote/FetchHostResponse.java
+++ b/geode-core/src/main/java/com/gemstone/gemfire/internal/admin/remote/FetchHostResponse.java
@@ -23,7 +23,7 @@ import com.gemstone.gemfire.distributed.internal.DistributionConfig;
import com.gemstone.gemfire.distributed.internal.DistributionManager;
import com.gemstone.gemfire.distributed.internal.membership.InternalDistributedMember;
import com.gemstone.gemfire.internal.GemFireVersion;
-import com.gemstone.gemfire.internal.SocketCreator;
+import com.gemstone.gemfire.internal.net.SocketCreator;
import com.gemstone.gemfire.internal.cache.CacheServerLauncher;
import com.gemstone.gemfire.internal.i18n.LocalizedStrings;
import com.gemstone.gemfire.internal.logging.LogService;
http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/c5ed7a6c/geode-core/src/main/java/com/gemstone/gemfire/internal/cache/CacheServerLauncher.java
----------------------------------------------------------------------
diff --git a/geode-core/src/main/java/com/gemstone/gemfire/internal/cache/CacheServerLauncher.java b/geode-core/src/main/java/com/gemstone/gemfire/internal/cache/CacheServerLauncher.java
index e8c6643..4b4f4ba 100755
--- a/geode-core/src/main/java/com/gemstone/gemfire/internal/cache/CacheServerLauncher.java
+++ b/geode-core/src/main/java/com/gemstone/gemfire/internal/cache/CacheServerLauncher.java
@@ -30,7 +30,7 @@ import com.gemstone.gemfire.distributed.internal.InternalDistributedSystem;
import com.gemstone.gemfire.i18n.LogWriterI18n;
import com.gemstone.gemfire.internal.OSProcess;
import com.gemstone.gemfire.internal.PureJavaMode;
-import com.gemstone.gemfire.internal.SocketCreator;
+import com.gemstone.gemfire.internal.net.SocketCreator;
import com.gemstone.gemfire.internal.cache.tier.sockets.CacheServerHelper;
import com.gemstone.gemfire.internal.i18n.LocalizedStrings;
import com.gemstone.gemfire.internal.process.StartupStatus;
http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/c5ed7a6c/geode-core/src/main/java/com/gemstone/gemfire/internal/cache/GemFireCacheImpl.java
----------------------------------------------------------------------
diff --git a/geode-core/src/main/java/com/gemstone/gemfire/internal/cache/GemFireCacheImpl.java b/geode-core/src/main/java/com/gemstone/gemfire/internal/cache/GemFireCacheImpl.java
index a9e1631..8c8c747 100755
--- a/geode-core/src/main/java/com/gemstone/gemfire/internal/cache/GemFireCacheImpl.java
+++ b/geode-core/src/main/java/com/gemstone/gemfire/internal/cache/GemFireCacheImpl.java
@@ -205,6 +205,7 @@ import com.gemstone.gemfire.internal.logging.InternalLogWriter;
import com.gemstone.gemfire.internal.logging.LogService;
import com.gemstone.gemfire.internal.logging.LoggingThreadGroup;
import com.gemstone.gemfire.internal.logging.log4j.LocalizedMessage;
+import com.gemstone.gemfire.internal.net.SocketCreator;
import com.gemstone.gemfire.internal.offheap.MemoryAllocator;
import com.gemstone.gemfire.internal.process.ClusterConfigurationNotAvailableException;
import com.gemstone.gemfire.internal.sequencelog.SequenceLoggerImpl;
http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/c5ed7a6c/geode-core/src/main/java/com/gemstone/gemfire/internal/cache/partitioned/RedundancyLogger.java
----------------------------------------------------------------------
diff --git a/geode-core/src/main/java/com/gemstone/gemfire/internal/cache/partitioned/RedundancyLogger.java b/geode-core/src/main/java/com/gemstone/gemfire/internal/cache/partitioned/RedundancyLogger.java
index f7e8621..1191c07 100644
--- a/geode-core/src/main/java/com/gemstone/gemfire/internal/cache/partitioned/RedundancyLogger.java
+++ b/geode-core/src/main/java/com/gemstone/gemfire/internal/cache/partitioned/RedundancyLogger.java
@@ -31,7 +31,7 @@ import java.util.concurrent.CountDownLatch;
import org.apache.logging.log4j.Logger;
import com.gemstone.gemfire.distributed.internal.membership.InternalDistributedMember;
-import com.gemstone.gemfire.internal.SocketCreator;
+import com.gemstone.gemfire.internal.net.SocketCreator;
import com.gemstone.gemfire.internal.cache.BucketPersistenceAdvisor;
import com.gemstone.gemfire.internal.cache.ColocationHelper;
import com.gemstone.gemfire.internal.cache.DiskStoreImpl;
http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/c5ed7a6c/geode-core/src/main/java/com/gemstone/gemfire/internal/cache/persistence/PersistentMemberPattern.java
----------------------------------------------------------------------
diff --git a/geode-core/src/main/java/com/gemstone/gemfire/internal/cache/persistence/PersistentMemberPattern.java b/geode-core/src/main/java/com/gemstone/gemfire/internal/cache/persistence/PersistentMemberPattern.java
index a0e1f0a..02d6212 100644
--- a/geode-core/src/main/java/com/gemstone/gemfire/internal/cache/persistence/PersistentMemberPattern.java
+++ b/geode-core/src/main/java/com/gemstone/gemfire/internal/cache/persistence/PersistentMemberPattern.java
@@ -24,7 +24,7 @@ import java.util.UUID;
import com.gemstone.gemfire.DataSerializer;
import com.gemstone.gemfire.cache.persistence.PersistentID;
-import com.gemstone.gemfire.internal.SocketCreator;
+import com.gemstone.gemfire.internal.net.SocketCreator;
/**
* Implementation of the public PersistentID. It holds the region,
http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/c5ed7a6c/geode-core/src/main/java/com/gemstone/gemfire/internal/cache/tier/sockets/AcceptorImpl.java
----------------------------------------------------------------------
diff --git a/geode-core/src/main/java/com/gemstone/gemfire/internal/cache/tier/sockets/AcceptorImpl.java b/geode-core/src/main/java/com/gemstone/gemfire/internal/cache/tier/sockets/AcceptorImpl.java
index 4f952a8..ba04933 100644
--- a/geode-core/src/main/java/com/gemstone/gemfire/internal/cache/tier/sockets/AcceptorImpl.java
+++ b/geode-core/src/main/java/com/gemstone/gemfire/internal/cache/tier/sockets/AcceptorImpl.java
@@ -69,13 +69,8 @@ import com.gemstone.gemfire.cache.RegionDestroyedException;
import com.gemstone.gemfire.cache.client.internal.PoolImpl;
import com.gemstone.gemfire.cache.server.CacheServer;
import com.gemstone.gemfire.cache.wan.GatewayTransportFilter;
-import com.gemstone.gemfire.distributed.internal.DM;
-import com.gemstone.gemfire.distributed.internal.DistributionConfig;
-import com.gemstone.gemfire.distributed.internal.InternalDistributedSystem;
-import com.gemstone.gemfire.distributed.internal.LonerDistributionManager;
-import com.gemstone.gemfire.distributed.internal.PooledExecutorWithDMStats;
-import com.gemstone.gemfire.distributed.internal.ReplyProcessor21;
-import com.gemstone.gemfire.internal.SocketCreator;
+import com.gemstone.gemfire.distributed.internal.*;
+import com.gemstone.gemfire.internal.net.SocketCreator;
import com.gemstone.gemfire.internal.SystemTimer;
import com.gemstone.gemfire.internal.cache.BucketAdvisor;
import com.gemstone.gemfire.internal.cache.BucketAdvisor.BucketProfile;
@@ -91,6 +86,7 @@ import com.gemstone.gemfire.internal.logging.LogService;
import com.gemstone.gemfire.internal.logging.LoggingThreadGroup;
import com.gemstone.gemfire.internal.logging.log4j.LocalizedMessage;
import com.gemstone.gemfire.internal.security.GeodeSecurityUtil;
+import com.gemstone.gemfire.internal.net.SocketCreatorFactory;
import com.gemstone.gemfire.internal.tcp.ConnectionTable;
import com.gemstone.gemfire.internal.util.ArrayUtils;
@@ -291,7 +287,7 @@ public class AcceptorImpl extends Acceptor implements Runnable
* The maximum time between client pings. This value is used by the
* <code>ClientHealthMonitor</code> to monitor the health of this
* server's clients.
- * @param c
+ * @param internalCache
* The GemFire cache whose contents is served to clients
* @param maxConnections
* the maximum number of connections allowed in the server pool
@@ -305,14 +301,14 @@ public class AcceptorImpl extends Acceptor implements Runnable
public AcceptorImpl(int port,
String bindHostName, boolean notifyBySubscription,
int socketBufferSize, int maximumTimeBetweenPings,
- InternalCache c, int maxConnections, int maxThreads,
+ InternalCache internalCache, int maxConnections, int maxThreads,
int maximumMessageCount, int messageTimeToLive,
ConnectionListener listener,List overflowAttributesList,
boolean isGatewayReceiver, List<GatewayTransportFilter> transportFilter,
boolean tcpNoDelay)
throws IOException
{
- this.bindHostName = calcBindHostName(c, bindHostName);
+ this.bindHostName = calcBindHostName(internalCache, bindHostName);
this.connectionListener = listener == null ? new ConnectionListenerAdapter() : listener;
this.notifyBySubscription = notifyBySubscription;
this.isGatewayReceiver = isGatewayReceiver;
@@ -373,7 +369,7 @@ public class AcceptorImpl extends Acceptor implements Runnable
tmp_commQ = new LinkedBlockingQueue();
tmp_hs = new HashSet(512);
tmp_timer = new SystemTimer(
- c.getDistributedSystem(), true);
+ internalCache.getDistributedSystem(), true);
}
this.selector = tmp_s;
//this.tmpSel = tmp2_s;
@@ -385,21 +381,11 @@ public class AcceptorImpl extends Acceptor implements Runnable
}
{
- final int backLog = Integer.getInteger(BACKLOG_PROPERTY_NAME, DEFAULT_BACKLOG).intValue();
- DistributionConfig config = ((InternalDistributedSystem)c.getDistributedSystem()).getConfig();
if(!isGatewayReceiver) {
//If configured use SSL properties for cache-server
- this.socketCreator = SocketCreator.createNonDefaultInstance(config.getServerSSLEnabled(),
- config.getServerSSLRequireAuthentication(),
- config.getServerSSLProtocols(),
- config.getServerSSLCiphers(),
- config.getServerSSLProperties());
+ this.socketCreator = SocketCreatorFactory.getServerSSLSocketCreator();
} else {
- this.socketCreator = SocketCreator.createNonDefaultInstance(config.getGatewaySSLEnabled(),
- config.getGatewaySSLRequireAuthentication(),
- config.getGatewaySSLProtocols(),
- config.getGatewaySSLCiphers(),
- config.getGatewaySSLProperties());
+ this.socketCreator = SocketCreatorFactory.getGatewaySSLSocketCreator();
}
final GemFireCacheImpl gc;
@@ -409,6 +395,7 @@ public class AcceptorImpl extends Acceptor implements Runnable
else {
gc = null;
}
+ final int backLog = Integer.getInteger(BACKLOG_PROPERTY_NAME, DEFAULT_BACKLOG).intValue();
final long tilt = System.currentTimeMillis() + 120 * 1000;
if (isSelector()) {
@@ -429,8 +416,7 @@ public class AcceptorImpl extends Acceptor implements Runnable
// immediately restarted, which sometimes results in a bind exception
for (;;) {
try {
- this.serverSock.bind(new InetSocketAddress(getBindAddress(), port),
- backLog);
+ this.serverSock.bind(new InetSocketAddress(getBindAddress(), port), backLog);
break;
}
catch (SocketException b) {
@@ -519,16 +505,16 @@ public class AcceptorImpl extends Acceptor implements Runnable
}
- this.cache = c;
+ this.cache = internalCache;
this.crHelper = new CachedRegionHelper(this.cache);
this.clientNotifier = CacheClientNotifier.getInstance(cache, this.stats,
- maximumMessageCount,messageTimeToLive,
+ maximumMessageCount,messageTimeToLive,
connectionListener,overflowAttributesList, isGatewayReceiver);
this.socketBufferSize = socketBufferSize;
// Create the singleton ClientHealthMonitor
- this.healthMonitor = ClientHealthMonitor.getInstance(c, maximumTimeBetweenPings,
+ this.healthMonitor = ClientHealthMonitor.getInstance(internalCache, maximumTimeBetweenPings,
this.clientNotifier.getStats());
{
http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/c5ed7a6c/geode-core/src/main/java/com/gemstone/gemfire/internal/cache/tier/sockets/CacheClientNotifier.java
----------------------------------------------------------------------
diff --git a/geode-core/src/main/java/com/gemstone/gemfire/internal/cache/tier/sockets/CacheClientNotifier.java b/geode-core/src/main/java/com/gemstone/gemfire/internal/cache/tier/sockets/CacheClientNotifier.java
index d351569..bfdded9 100755
--- a/geode-core/src/main/java/com/gemstone/gemfire/internal/cache/tier/sockets/CacheClientNotifier.java
+++ b/geode-core/src/main/java/com/gemstone/gemfire/internal/cache/tier/sockets/CacheClientNotifier.java
@@ -118,6 +118,7 @@ import com.gemstone.gemfire.internal.i18n.LocalizedStrings;
import com.gemstone.gemfire.internal.logging.InternalLogWriter;
import com.gemstone.gemfire.internal.logging.LogService;
import com.gemstone.gemfire.internal.logging.log4j.LocalizedMessage;
+import com.gemstone.gemfire.internal.net.SocketCloser;
import com.gemstone.gemfire.security.AccessControl;
import com.gemstone.gemfire.security.AuthenticationFailedException;
import com.gemstone.gemfire.security.AuthenticationRequiredException;
http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/c5ed7a6c/geode-core/src/main/java/com/gemstone/gemfire/internal/cache/tier/sockets/CacheClientUpdater.java
----------------------------------------------------------------------
diff --git a/geode-core/src/main/java/com/gemstone/gemfire/internal/cache/tier/sockets/CacheClientUpdater.java b/geode-core/src/main/java/com/gemstone/gemfire/internal/cache/tier/sockets/CacheClientUpdater.java
index 391c3e6..8f81196 100644
--- a/geode-core/src/main/java/com/gemstone/gemfire/internal/cache/tier/sockets/CacheClientUpdater.java
+++ b/geode-core/src/main/java/com/gemstone/gemfire/internal/cache/tier/sockets/CacheClientUpdater.java
@@ -43,6 +43,7 @@ import com.gemstone.gemfire.internal.logging.LogService;
import com.gemstone.gemfire.internal.logging.LoggingThreadGroup;
import com.gemstone.gemfire.internal.logging.log4j.LocalizedMessage;
import com.gemstone.gemfire.internal.logging.log4j.LogMarker;
+import com.gemstone.gemfire.internal.net.SocketCreator;
import com.gemstone.gemfire.internal.offheap.annotations.Released;
import com.gemstone.gemfire.internal.sequencelog.EntryLogger;
import com.gemstone.gemfire.security.AuthenticationFailedException;
http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/c5ed7a6c/geode-core/src/main/java/com/gemstone/gemfire/internal/cache/tier/sockets/CacheServerStats.java
----------------------------------------------------------------------
diff --git a/geode-core/src/main/java/com/gemstone/gemfire/internal/cache/tier/sockets/CacheServerStats.java b/geode-core/src/main/java/com/gemstone/gemfire/internal/cache/tier/sockets/CacheServerStats.java
index 38537fa..3dbc48f 100644
--- a/geode-core/src/main/java/com/gemstone/gemfire/internal/cache/tier/sockets/CacheServerStats.java
+++ b/geode-core/src/main/java/com/gemstone/gemfire/internal/cache/tier/sockets/CacheServerStats.java
@@ -20,8 +20,6 @@
*/
package com.gemstone.gemfire.internal.cache.tier.sockets;
-import java.net.InetAddress;
-
import com.gemstone.gemfire.StatisticDescriptor;
import com.gemstone.gemfire.Statistics;
import com.gemstone.gemfire.StatisticsFactory;
@@ -29,9 +27,7 @@ import com.gemstone.gemfire.StatisticsType;
import com.gemstone.gemfire.cache.server.ServerLoad;
import com.gemstone.gemfire.distributed.internal.InternalDistributedSystem;
import com.gemstone.gemfire.distributed.internal.PoolStatHelper;
-import com.gemstone.gemfire.internal.DummyStatisticsFactory;
-import com.gemstone.gemfire.internal.SocketCreator;
-import com.gemstone.gemfire.internal.util.ArrayUtils;
+import com.gemstone.gemfire.internal.net.SocketCreator;
public class CacheServerStats implements MessageStats {
http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/c5ed7a6c/geode-core/src/main/java/com/gemstone/gemfire/internal/cache/xmlcache/GatewayReceiverCreation.java
----------------------------------------------------------------------
diff --git a/geode-core/src/main/java/com/gemstone/gemfire/internal/cache/xmlcache/GatewayReceiverCreation.java b/geode-core/src/main/java/com/gemstone/gemfire/internal/cache/xmlcache/GatewayReceiverCreation.java
index e76d39a..511a03d 100644
--- a/geode-core/src/main/java/com/gemstone/gemfire/internal/cache/xmlcache/GatewayReceiverCreation.java
+++ b/geode-core/src/main/java/com/gemstone/gemfire/internal/cache/xmlcache/GatewayReceiverCreation.java
@@ -27,7 +27,7 @@ import com.gemstone.gemfire.cache.Cache;
import com.gemstone.gemfire.cache.server.CacheServer;
import com.gemstone.gemfire.cache.wan.GatewayReceiver;
import com.gemstone.gemfire.cache.wan.GatewayTransportFilter;
-import com.gemstone.gemfire.internal.SocketCreator;
+import com.gemstone.gemfire.internal.net.SocketCreator;
import com.gemstone.gemfire.internal.i18n.LocalizedStrings;
import com.gemstone.gemfire.internal.logging.LogService;
import com.gemstone.gemfire.internal.logging.log4j.LocalizedMessage;
http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/c5ed7a6c/geode-core/src/main/java/com/gemstone/gemfire/internal/net/SocketCloser.java
----------------------------------------------------------------------
diff --git a/geode-core/src/main/java/com/gemstone/gemfire/internal/net/SocketCloser.java b/geode-core/src/main/java/com/gemstone/gemfire/internal/net/SocketCloser.java
new file mode 100644
index 0000000..bf7981f
--- /dev/null
+++ b/geode-core/src/main/java/com/gemstone/gemfire/internal/net/SocketCloser.java
@@ -0,0 +1,257 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.gemstone.gemfire.internal.net;
+
+import java.io.IOException;
+import java.net.Socket;
+import java.util.HashMap;
+import java.util.concurrent.BlockingQueue;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.Future;
+import java.util.concurrent.LinkedBlockingQueue;
+import java.util.concurrent.ThreadFactory;
+import java.util.concurrent.ThreadPoolExecutor;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
+
+import org.apache.logging.log4j.Logger;
+
+import com.gemstone.gemfire.SystemFailure;
+import com.gemstone.gemfire.internal.logging.LogService;
+import com.gemstone.gemfire.internal.logging.LoggingThreadGroup;
+
+/**
+ * This class allows sockets to be closed without blocking.
+ * In some cases we have seen a call of socket.close block for minutes.
+ * This class maintains a thread pool for every other member we have
+ * connected sockets to. Any request to close by default returns immediately
+ * to the caller while the close is called by a background thread.
+ * The requester can wait for a configured amount of time by setting
+ * the "p2p.ASYNC_CLOSE_WAIT_MILLISECONDS" system property.
+ * Idle threads that are not doing a close will timeout after 2 minutes.
+ * This can be configured by setting the
+ * "p2p.ASYNC_CLOSE_POOL_KEEP_ALIVE_SECONDS" system property.
+ * A pool exists for each remote address that we have a socket connected to.
+ * That way if close is taking a long time to one address we can still get closes
+ * done to another address.
+ * Each address pool by default has at most 8 threads. This max threads can be
+ * configured using the "p2p.ASYNC_CLOSE_POOL_MAX_THREADS" system property.
+ */
+public class SocketCloser {
+ private static final Logger logger = LogService.getLogger();
+ /** Number of seconds to wait before timing out an unused async close thread. Default is 120 (2 minutes). */
+ static final long ASYNC_CLOSE_POOL_KEEP_ALIVE_SECONDS = Long.getLong("p2p.ASYNC_CLOSE_POOL_KEEP_ALIVE_SECONDS", 120).longValue();
+ /** Maximum number of threads that can be doing a socket close. Any close requests over this max will queue up waiting for a thread. */
+ static final int ASYNC_CLOSE_POOL_MAX_THREADS = Integer.getInteger("p2p.ASYNC_CLOSE_POOL_MAX_THREADS", 8).intValue();
+ /** How many milliseconds the synchronous requester waits for the async close to happen. Default is 0. Prior releases waited 50ms. */
+ static final long ASYNC_CLOSE_WAIT_MILLISECONDS = Long.getLong("p2p.ASYNC_CLOSE_WAIT_MILLISECONDS", 0).longValue();
+
+
+ /** map of thread pools of async close threads */
+ private final HashMap<String, ThreadPoolExecutor> asyncCloseExecutors = new HashMap<>();
+ private final long asyncClosePoolKeepAliveSeconds;
+ private final int asyncClosePoolMaxThreads;
+ private final long asyncCloseWaitTime;
+ private final TimeUnit asyncCloseWaitUnits;
+ private boolean closed;
+
+ public SocketCloser() {
+ this(ASYNC_CLOSE_POOL_KEEP_ALIVE_SECONDS, ASYNC_CLOSE_POOL_MAX_THREADS, ASYNC_CLOSE_WAIT_MILLISECONDS, TimeUnit.MILLISECONDS);
+ }
+ public SocketCloser(int asyncClosePoolMaxThreads, long asyncCloseWaitMillis) {
+ this(ASYNC_CLOSE_POOL_KEEP_ALIVE_SECONDS, asyncClosePoolMaxThreads, asyncCloseWaitMillis, TimeUnit.MILLISECONDS);
+ }
+ public SocketCloser(long asyncClosePoolKeepAliveSeconds, int asyncClosePoolMaxThreads, long asyncCloseWaitTime, TimeUnit asyncCloseWaitUnits) {
+ this.asyncClosePoolKeepAliveSeconds = asyncClosePoolKeepAliveSeconds;
+ this.asyncClosePoolMaxThreads = asyncClosePoolMaxThreads;
+ this.asyncCloseWaitTime = asyncCloseWaitTime;
+ this.asyncCloseWaitUnits = asyncCloseWaitUnits;
+ }
+
+ public int getMaxThreads() {
+ return this.asyncClosePoolMaxThreads;
+ }
+
+ private ThreadPoolExecutor getAsyncThreadExecutor(String address) {
+ synchronized (asyncCloseExecutors) {
+ ThreadPoolExecutor pool = asyncCloseExecutors.get(address);
+ if (pool == null) {
+ final ThreadGroup tg = LoggingThreadGroup.createThreadGroup("Socket asyncClose", logger);
+ ThreadFactory tf = new ThreadFactory() {
+ public Thread newThread(final Runnable command) {
+ Thread thread = new Thread(tg, command);
+ thread.setDaemon(true);
+ return thread;
+ }
+ };
+ BlockingQueue<Runnable> workQueue = new LinkedBlockingQueue<Runnable>();
+ pool = new ThreadPoolExecutor(this.asyncClosePoolMaxThreads, this.asyncClosePoolMaxThreads, this.asyncClosePoolKeepAliveSeconds, TimeUnit.SECONDS, workQueue, tf);
+ pool.allowCoreThreadTimeOut(true);
+ asyncCloseExecutors.put(address, pool);
+ }
+ return pool;
+ }
+ }
+ /**
+ * Call this method if you know all the resources in the closer
+ * for the given address are no longer needed.
+ * Currently a thread pool is kept for each address and if you
+ * know that an address no longer needs its pool then you should
+ * call this method.
+ */
+ public void releaseResourcesForAddress(String address) {
+ synchronized (asyncCloseExecutors) {
+ ThreadPoolExecutor pool = asyncCloseExecutors.get(address);
+ if (pool != null) {
+ pool.shutdown();
+ asyncCloseExecutors.remove(address);
+ }
+ }
+ }
+ private boolean isClosed() {
+ synchronized (asyncCloseExecutors) {
+ return this.closed;
+ }
+ }
+ /**
+ * Call close when you are all done with your socket closer.
+ * If you call asyncClose after close is called then the
+ * asyncClose will be done synchronously.
+ */
+ public void close() {
+ synchronized (asyncCloseExecutors) {
+ if (!this.closed) {
+ this.closed = true;
+ for (ThreadPoolExecutor pool: asyncCloseExecutors.values()) {
+ pool.shutdown();
+ }
+ asyncCloseExecutors.clear();
+ }
+ }
+ }
+ private void asyncExecute(String address, Runnable r) {
+ // Waiting 50ms for the async close request to complete is what the old (close per thread)
+ // code did. But now that we will not create a thread for every close request
+ // it seems better to let the thread that requested the close to move on quickly.
+ // So the default has changed to not wait. The system property p2p.ASYNC_CLOSE_WAIT_MILLISECONDS
+ // can be set to how many milliseconds to wait.
+ if (this.asyncCloseWaitTime == 0) {
+ getAsyncThreadExecutor(address).execute(r);
+ } else {
+ Future<?> future = getAsyncThreadExecutor(address).submit(r);
+ try {
+ future.get(this.asyncCloseWaitTime, this.asyncCloseWaitUnits);
+ } catch (InterruptedException | ExecutionException | TimeoutException e) {
+ // We want this code to wait at most 50ms for the close to happen.
+ // It is ok to ignore these exception and let the close continue
+ // in the background.
+ }
+ }
+ }
+ /**
+ * Closes the specified socket in a background thread.
+ * In some cases we see close hang (see bug 33665).
+ * Depending on how the SocketCloser is configured (see ASYNC_CLOSE_WAIT_MILLISECONDS)
+ * this method may block for a certain amount of time.
+ * If it is called after the SocketCloser is closed then a normal
+ * synchronous close is done.
+ * @param sock the socket to close
+ * @param address identifies who the socket is connected to
+ * @param extra an optional Runnable with stuff to execute in the async thread
+ */
+ public void asyncClose(final Socket sock, final String address, final Runnable extra) {
+ if (sock == null || sock.isClosed()) {
+ return;
+ }
+ boolean doItInline = false;
+ try {
+ synchronized (asyncCloseExecutors) {
+ if (isClosed()) {
+ // this SocketCloser has been closed so do a synchronous, inline, close
+ doItInline = true;
+ } else {
+ asyncExecute(address, new Runnable() {
+ public void run() {
+ Thread.currentThread().setName("AsyncSocketCloser for " + address);
+ try {
+ if (extra != null) {
+ extra.run();
+ }
+ inlineClose(sock);
+ } finally {
+ Thread.currentThread().setName("unused AsyncSocketCloser");
+ }
+ }
+ });
+ }
+ }
+ } catch (OutOfMemoryError ignore) {
+ // If we can't start a thread to close the socket just do it inline.
+ // See bug 50573.
+ doItInline = true;
+ }
+ if (doItInline) {
+ if (extra != null) {
+ extra.run();
+ }
+ inlineClose(sock);
+ }
+ }
+
+
+ /**
+ * Closes the specified socket
+ * @param sock the socket to close
+ */
+ private static void inlineClose(final Socket sock) {
+ // the next two statements are a mad attempt to fix bug
+ // 36041 - segv in jrockit in pthread signaling code. This
+ // seems to alleviate the problem.
+ try {
+ sock.shutdownInput();
+ sock.shutdownOutput();
+ } catch (Exception e) {
+ }
+ try {
+ sock.close();
+ } catch (IOException ignore) {
+ } catch (VirtualMachineError err) {
+ SystemFailure.initiateFailure(err);
+ // If this ever returns, rethrow the error. We're poisoned
+ // now, so don't let this thread continue.
+ throw err;
+ } catch (java.security.ProviderException pe) {
+ // some ssl implementations have trouble with termination and throw
+ // this exception. See bug #40783
+ } catch (Error e) {
+ // Whenever you catch Error or Throwable, you must also
+ // catch VirtualMachineError (see above). However, there is
+ // _still_ a possibility that you are dealing with a cascading
+ // error condition, so you also need to check to see if the JVM
+ // is still usable:
+ SystemFailure.checkFailure();
+ // Sun's NIO implementation has been known to throw Errors
+ // that are caused by IOExceptions. If this is the case, it's
+ // okay.
+ if (e.getCause() instanceof IOException) {
+ // okay...
+ } else {
+ throw e;
+ }
+ }
+ }
+}