Author: remm
Date: Tue Oct 27 15:05:45 2015
New Revision: 1710834

URL: http://svn.apache.org/viewvc?rev=1710834&view=rev
Log:
Remove "optimization" to avoid creating the SSLSession, since it is always used 
in Tomcat and looks cheap to create.

Modified:
    tomcat/trunk/java/org/apache/tomcat/util/net/openssl/OpenSSLEngine.java

Modified: 
tomcat/trunk/java/org/apache/tomcat/util/net/openssl/OpenSSLEngine.java
URL: 
http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/tomcat/util/net/openssl/OpenSSLEngine.java?rev=1710834&r1=1710833&r2=1710834&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/tomcat/util/net/openssl/OpenSSLEngine.java 
(original)
+++ tomcat/trunk/java/org/apache/tomcat/util/net/openssl/OpenSSLEngine.java Tue 
Oct 27 15:05:45 2015
@@ -30,7 +30,6 @@ import java.util.List;
 import java.util.Map;
 import java.util.Set;
 import java.util.concurrent.atomic.AtomicIntegerFieldUpdater;
-import java.util.concurrent.atomic.AtomicReferenceFieldUpdater;
 
 import javax.net.ssl.SSLEngine;
 import javax.net.ssl.SSLEngineResult;
@@ -107,7 +106,6 @@ public final class OpenSSLEngine extends
         RENEGOTIATION_UNSUPPORTED.setStackTrace(new StackTraceElement[0]);
         ENCRYPTED_PACKET_OVERSIZED.setStackTrace(new StackTraceElement[0]);
         DESTROYED_UPDATER = 
AtomicIntegerFieldUpdater.newUpdater(OpenSSLEngine.class, "destroyed");
-        SESSION_UPDATER = 
AtomicReferenceFieldUpdater.newUpdater(OpenSSLEngine.class, SSLSession.class, 
"session");
     }
 
     private static final int MAX_PLAINTEXT_LENGTH = 16 * 1024; // 2^14
@@ -140,7 +138,6 @@ public final class OpenSSLEngine extends
     }
 
     private static final AtomicIntegerFieldUpdater<OpenSSLEngine> 
DESTROYED_UPDATER;
-    private static final AtomicReferenceFieldUpdater<OpenSSLEngine, 
SSLSession> SESSION_UPDATER;
 
     private static final String INVALID_CIPHER = "SSL_NULL_WITH_NULL_NULL";
 
@@ -180,7 +177,7 @@ public final class OpenSSLEngine extends
 
     private String selectedProtocol = null;
 
-    private volatile SSLSession session;
+    private final OpenSSLSession session;
 
     /**
      * Creates a new instance
@@ -198,6 +195,7 @@ public final class OpenSSLEngine extends
         if (sslCtx == 0) {
             throw new 
IllegalArgumentException(sm.getString("engine.noSSLContext"));
         }
+        session = new OpenSSLSession();
         ssl = SSL.newSSL(sslCtx, !clientMode);
         networkBIO = SSL.makeNetworkBIO(ssl);
         this.fallbackApplicationProtocol = fallbackApplicationProtocol;
@@ -427,12 +425,12 @@ public final class OpenSSLEngine extends
             // Do we have enough room in dst to write encrypted data?
             int capacity = dst.remaining();
             if (capacity < pendingNet) {
-                return new 
SSLEngineResult(SSLEngineResult.Status.BUFFER_OVERFLOW, handshakeStatus, 0, 
bytesProduced);
+                return new 
SSLEngineResult(SSLEngineResult.Status.BUFFER_OVERFLOW, handshakeStatus, 0, 0);
             }
 
             // Write the pending data from the network BIO into the dst buffer
             try {
-                bytesProduced += readEncryptedData(dst, pendingNet);
+                bytesProduced = readEncryptedData(dst, pendingNet);
             } catch (Exception e) {
                 throw new SSLException(e);
             }
@@ -879,242 +877,6 @@ public final class OpenSSLEngine extends
 
     @Override
     public SSLSession getSession() {
-        // A other methods on SSLEngine are thread-safe we also need to make 
this thread-safe...
-        SSLSession session = this.session;
-        if (session == null) {
-            session = new SSLSession() {
-                // SSLSession implementation seems to not need to be 
thread-safe so no need for volatile etc.
-                private X509Certificate[] x509PeerCerts;
-
-                // lazy init for memory reasons
-                private Map<String, Object> values;
-
-                @Override
-                public byte[] getId() {
-                    // We don't cache that to keep memory usage to a minimum.
-                    byte[] id = SSL.getSessionId(ssl);
-                    if (id == null) {
-                        // The id should never be null, if it was null then 
the SESSION itself was not valid.
-                        throw new 
IllegalStateException(sm.getString("engine.noSession"));
-                    }
-                    return id;
-                }
-
-                @Override
-                public SSLSessionContext getSessionContext() {
-                    return sessionContext;
-                }
-
-                @Override
-                public long getCreationTime() {
-                    // We need ot multiple by 1000 as openssl uses seconds and 
we need milli-seconds.
-                    return SSL.getTime(ssl) * 1000L;
-                }
-
-                @Override
-                public long getLastAccessedTime() {
-                    // TODO: Add proper implementation
-                    return getCreationTime();
-                }
-
-                @Override
-                public void invalidate() {
-                    // NOOP
-                }
-
-                @Override
-                public boolean isValid() {
-                    return false;
-                }
-
-                @Override
-                public void putValue(String name, Object value) {
-                    if (name == null) {
-                        throw new 
IllegalArgumentException(sm.getString("engine.nullName"));
-                    }
-                    if (value == null) {
-                        throw new 
IllegalArgumentException(sm.getString("engine.nullValue"));
-                    }
-                    Map<String, Object> values = this.values;
-                    if (values == null) {
-                        // Use size of 2 to keep the memory overhead small
-                        values = this.values = new HashMap<>(2);
-                    }
-                    Object old = values.put(name, value);
-                    if (value instanceof SSLSessionBindingListener) {
-                        ((SSLSessionBindingListener) value).valueBound(new 
SSLSessionBindingEvent(this, name));
-                    }
-                    notifyUnbound(old, name);
-                }
-
-                @Override
-                public Object getValue(String name) {
-                    if (name == null) {
-                        throw new 
IllegalArgumentException(sm.getString("engine.nullName"));
-                    }
-                    if (values == null) {
-                        return null;
-                    }
-                    return values.get(name);
-                }
-
-                @Override
-                public void removeValue(String name) {
-                    if (name == null) {
-                        throw new 
IllegalArgumentException(sm.getString("engine.nullName"));
-                    }
-                    Map<String, Object> values = this.values;
-                    if (values == null) {
-                        return;
-                    }
-                    Object old = values.remove(name);
-                    notifyUnbound(old, name);
-                }
-
-                @Override
-                public String[] getValueNames() {
-                    Map<String, Object> values = this.values;
-                    if (values == null || values.isEmpty()) {
-                        return new String[0];
-                    }
-                    return values.keySet().toArray(new String[values.size()]);
-                }
-
-                private void notifyUnbound(Object value, String name) {
-                    if (value instanceof SSLSessionBindingListener) {
-                        ((SSLSessionBindingListener) value).valueUnbound(new 
SSLSessionBindingEvent(this, name));
-                    }
-                }
-
-                @Override
-                public Certificate[] getPeerCertificates() throws 
SSLPeerUnverifiedException {
-                    // these are lazy created to reduce memory overhead
-                    Certificate[] c = peerCerts;
-                    if (c == null) {
-                        if (SSL.isInInit(ssl) != 0) {
-                            throw new 
SSLPeerUnverifiedException(sm.getString("engine.unverifiedPeer"));
-                        }
-                        c = peerCerts = initPeerCertChain();
-                    }
-                    return c;
-                }
-
-                @Override
-                public Certificate[] getLocalCertificates() {
-                    // TODO: Find out how to get these
-                    return EMPTY_CERTIFICATES;
-                }
-
-                @Override
-                public X509Certificate[] getPeerCertificateChain() throws 
SSLPeerUnverifiedException {
-                    // these are lazy created to reduce memory overhead
-                    X509Certificate[] c = x509PeerCerts;
-                    if (c == null) {
-                        if (SSL.isInInit(ssl) != 0) {
-                            throw new 
SSLPeerUnverifiedException(sm.getString("engine.unverifiedPeer"));
-                        }
-                        byte[][] chain = SSL.getPeerCertChain(ssl);
-                        if (chain == null) {
-                            throw new 
SSLPeerUnverifiedException(sm.getString("engine.unverifiedPeer"));
-                        }
-                        X509Certificate[] peerCerts = new 
X509Certificate[chain.length];
-                        for (int i = 0; i < peerCerts.length; i++) {
-                            try {
-                                peerCerts[i] = 
X509Certificate.getInstance(chain[i]);
-                            } catch (CertificateException e) {
-                                throw new IllegalStateException(e);
-                            }
-                        }
-                        c = x509PeerCerts = peerCerts;
-                    }
-                    return c;
-                }
-
-                @Override
-                public Principal getPeerPrincipal() throws 
SSLPeerUnverifiedException {
-                    Certificate[] peer = getPeerCertificates();
-                    if (peer == null || peer.length == 0) {
-                        return null;
-                    }
-                    return principal(peer);
-                }
-
-                @Override
-                public Principal getLocalPrincipal() {
-                    Certificate[] local = getLocalCertificates();
-                    if (local == null || local.length == 0) {
-                        return null;
-                    }
-                    return principal(local);
-                }
-
-                private Principal principal(Certificate[] certs) {
-                    return ((java.security.cert.X509Certificate) 
certs[0]).getIssuerX500Principal();
-                }
-
-                @Override
-                public String getCipherSuite() {
-                    if (!handshakeFinished) {
-                        return INVALID_CIPHER;
-                    }
-                    if (cipher == null) {
-                        String c = toJavaCipherSuite(SSL.getCipherForSSL(ssl));
-                        if (c != null) {
-                            cipher = c;
-                        }
-                    }
-                    return cipher;
-                }
-
-                @Override
-                public String getProtocol() {
-                    String applicationProtocol = 
OpenSSLEngine.this.applicationProtocol;
-                    if (applicationProtocol == null) {
-                        applicationProtocol = SSL.getNextProtoNegotiated(ssl);
-                        if (applicationProtocol == null) {
-                            applicationProtocol = fallbackApplicationProtocol;
-                        }
-                        if (applicationProtocol != null) {
-                            OpenSSLEngine.this.applicationProtocol = 
applicationProtocol.replace(':', '_');
-                        } else {
-                            OpenSSLEngine.this.applicationProtocol = 
applicationProtocol = "";
-                        }
-                    }
-                    String version = SSL.getVersion(ssl);
-                    if (applicationProtocol.isEmpty()) {
-                        return version;
-                    } else {
-                        return version + ':' + applicationProtocol;
-                    }
-                }
-
-                @Override
-                public String getPeerHost() {
-                    return null;
-                }
-
-                @Override
-                public int getPeerPort() {
-                    return 0;
-                }
-
-                @Override
-                public int getPacketBufferSize() {
-                    return MAX_ENCRYPTED_PACKET_LENGTH;
-                }
-
-                @Override
-                public int getApplicationBufferSize() {
-                    return MAX_PLAINTEXT_LENGTH;
-                }
-            };
-
-            if (!SESSION_UPDATER.compareAndSet(this, null, session)) {
-                // Was lazy created in the meantime so get the current 
reference.
-                session = this.session;
-            }
-        }
-
         return session;
     }
 
@@ -1176,6 +938,7 @@ public final class OpenSSLEngine extends
                     selectedProtocol = SSL.getNextProtoNegotiated(ssl);
                 }
             }
+            session.lastAccessedTime = System.currentTimeMillis();
             // if SSL_do_handshake returns > 0 it means the handshake was 
finished. This means we can update
             // handshakeFinished directly and so eliminate unnecessary calls 
to SSL.isInInit(...)
             handshakeFinished = true;
@@ -1212,6 +975,7 @@ public final class OpenSSLEngine extends
                         selectedProtocol = SSL.getNextProtoNegotiated(ssl);
                     }
                 }
+                session.lastAccessedTime = System.currentTimeMillis();
                 handshakeFinished = true;
                 return SSLEngineResult.HandshakeStatus.FINISHED;
             }
@@ -1343,4 +1107,238 @@ public final class OpenSSLEngine extends
         // Call shutdown as the user may have created the OpenSslEngine and 
not used it at all.
         shutdown();
     }
+
+    private class OpenSSLSession implements SSLSession {
+
+        // SSLSession implementation seems to not need to be thread-safe so no 
need for volatile etc.
+        private X509Certificate[] x509PeerCerts;
+
+        // lazy init for memory reasons
+        private Map<String, Object> values;
+
+        // Last accessed time
+        private long lastAccessedTime = -1;
+
+        @Override
+        public byte[] getId() {
+            // We don't cache that to keep memory usage to a minimum.
+            byte[] id = SSL.getSessionId(ssl);
+            if (id == null) {
+                // The id should never be null, if it was null then the 
SESSION itself was not valid.
+                throw new 
IllegalStateException(sm.getString("engine.noSession"));
+            }
+            return id;
+        }
+
+        @Override
+        public SSLSessionContext getSessionContext() {
+            return sessionContext;
+        }
+
+        @Override
+        public long getCreationTime() {
+            // We need ot multiple by 1000 as openssl uses seconds and we need 
milli-seconds.
+            return SSL.getTime(ssl) * 1000L;
+        }
+
+        @Override
+        public long getLastAccessedTime() {
+            return (lastAccessedTime > 0) ? lastAccessedTime : 
getCreationTime();
+        }
+
+        @Override
+        public void invalidate() {
+            // NOOP
+        }
+
+        @Override
+        public boolean isValid() {
+            return false;
+        }
+
+        @Override
+        public void putValue(String name, Object value) {
+            if (name == null) {
+                throw new 
IllegalArgumentException(sm.getString("engine.nullName"));
+            }
+            if (value == null) {
+                throw new 
IllegalArgumentException(sm.getString("engine.nullValue"));
+            }
+            Map<String, Object> values = this.values;
+            if (values == null) {
+                // Use size of 2 to keep the memory overhead small
+                values = this.values = new HashMap<>(2);
+            }
+            Object old = values.put(name, value);
+            if (value instanceof SSLSessionBindingListener) {
+                ((SSLSessionBindingListener) value).valueBound(new 
SSLSessionBindingEvent(this, name));
+            }
+            notifyUnbound(old, name);
+        }
+
+        @Override
+        public Object getValue(String name) {
+            if (name == null) {
+                throw new 
IllegalArgumentException(sm.getString("engine.nullName"));
+            }
+            if (values == null) {
+                return null;
+            }
+            return values.get(name);
+        }
+
+        @Override
+        public void removeValue(String name) {
+            if (name == null) {
+                throw new 
IllegalArgumentException(sm.getString("engine.nullName"));
+            }
+            Map<String, Object> values = this.values;
+            if (values == null) {
+                return;
+            }
+            Object old = values.remove(name);
+            notifyUnbound(old, name);
+        }
+
+        @Override
+        public String[] getValueNames() {
+            Map<String, Object> values = this.values;
+            if (values == null || values.isEmpty()) {
+                return new String[0];
+            }
+            return values.keySet().toArray(new String[values.size()]);
+        }
+
+        private void notifyUnbound(Object value, String name) {
+            if (value instanceof SSLSessionBindingListener) {
+                ((SSLSessionBindingListener) value).valueUnbound(new 
SSLSessionBindingEvent(this, name));
+            }
+        }
+
+        @Override
+        public Certificate[] getPeerCertificates() throws 
SSLPeerUnverifiedException {
+            // these are lazy created to reduce memory overhead
+            Certificate[] c = peerCerts;
+            if (c == null) {
+                if (SSL.isInInit(ssl) != 0) {
+                    throw new 
SSLPeerUnverifiedException(sm.getString("engine.unverifiedPeer"));
+                }
+                c = peerCerts = initPeerCertChain();
+            }
+            return c;
+        }
+
+        @Override
+        public Certificate[] getLocalCertificates() {
+            // FIXME: Not currently exposed by the native API
+            return EMPTY_CERTIFICATES;
+        }
+
+        @Override
+        public X509Certificate[] getPeerCertificateChain() throws 
SSLPeerUnverifiedException {
+            // these are lazy created to reduce memory overhead
+            X509Certificate[] c = x509PeerCerts;
+            if (c == null) {
+                if (SSL.isInInit(ssl) != 0) {
+                    throw new 
SSLPeerUnverifiedException(sm.getString("engine.unverifiedPeer"));
+                }
+                byte[][] chain = SSL.getPeerCertChain(ssl);
+                if (chain == null) {
+                    throw new 
SSLPeerUnverifiedException(sm.getString("engine.unverifiedPeer"));
+                }
+                X509Certificate[] peerCerts = new 
X509Certificate[chain.length];
+                for (int i = 0; i < peerCerts.length; i++) {
+                    try {
+                        peerCerts[i] = X509Certificate.getInstance(chain[i]);
+                    } catch (CertificateException e) {
+                        throw new IllegalStateException(e);
+                    }
+                }
+                c = x509PeerCerts = peerCerts;
+            }
+            return c;
+        }
+
+        @Override
+        public Principal getPeerPrincipal() throws SSLPeerUnverifiedException {
+            Certificate[] peer = getPeerCertificates();
+            if (peer == null || peer.length == 0) {
+                return null;
+            }
+            return principal(peer);
+        }
+
+        @Override
+        public Principal getLocalPrincipal() {
+            Certificate[] local = getLocalCertificates();
+            if (local == null || local.length == 0) {
+                return null;
+            }
+            return principal(local);
+        }
+
+        private Principal principal(Certificate[] certs) {
+            return ((java.security.cert.X509Certificate) 
certs[0]).getIssuerX500Principal();
+        }
+
+        @Override
+        public String getCipherSuite() {
+            if (!handshakeFinished) {
+                return INVALID_CIPHER;
+            }
+            if (cipher == null) {
+                String c = toJavaCipherSuite(SSL.getCipherForSSL(ssl));
+                if (c != null) {
+                    cipher = c;
+                }
+            }
+            return cipher;
+        }
+
+        @Override
+        public String getProtocol() {
+            String applicationProtocol = 
OpenSSLEngine.this.applicationProtocol;
+            if (applicationProtocol == null) {
+                applicationProtocol = SSL.getNextProtoNegotiated(ssl);
+                if (applicationProtocol == null) {
+                    applicationProtocol = fallbackApplicationProtocol;
+                }
+                if (applicationProtocol != null) {
+                    OpenSSLEngine.this.applicationProtocol = 
applicationProtocol.replace(':', '_');
+                } else {
+                    OpenSSLEngine.this.applicationProtocol = 
applicationProtocol = "";
+                }
+            }
+            String version = SSL.getVersion(ssl);
+            if (applicationProtocol.isEmpty()) {
+                return version;
+            } else {
+                return version + ':' + applicationProtocol;
+            }
+        }
+
+        @Override
+        public String getPeerHost() {
+            // Not available for now in Tomcat (needs to be passed during 
engine creation)
+            return null;
+        }
+
+        @Override
+        public int getPeerPort() {
+            // Not available for now in Tomcat (needs to be passed during 
engine creation)
+            return 0;
+        }
+
+        @Override
+        public int getPacketBufferSize() {
+            return MAX_ENCRYPTED_PACKET_LENGTH;
+        }
+
+        @Override
+        public int getApplicationBufferSize() {
+            return MAX_PLAINTEXT_LENGTH;
+        }
+
+    }
+
 }



---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org
For additional commands, e-mail: dev-h...@tomcat.apache.org

Reply via email to