@Override boolean isValid() { long creationTimeMillis = getCreationTime(); // Use the minimum of the timeout from the context and the session. long timeoutMillis = Math.max(0, Math.min(context.getSessionTimeout(), NativeCrypto.SSL_SESSION_get_timeout(ref.address))) * 1000; return (System.currentTimeMillis() - timeoutMillis) < creationTimeMillis; }
/** * Adds the given session to the cache. */ final void cacheSession(NativeSslSession session) { byte[] id = session.getId(); if (id == null || id.length == 0) { return; } synchronized (sessions) { ByteArray key = new ByteArray(id); if (sessions.containsKey(key)) { removeSession(sessions.get(key)); } // Let the subclass know. onBeforeAddSession(session); sessions.put(key, session); } }
/** * Makes sure cache size is < maximumSize. */ private void trimToSize() { synchronized (sessions) { int size = sessions.size(); if (size > maximumSize) { int removals = size - maximumSize; Iterator<NativeSslSession> i = sessions.values().iterator(); while (removals-- > 0) { NativeSslSession session = i.next(); onBeforeRemoveSession(session); i.remove(); } } } } }
/** * Called for server sessions only. Retrieves the session by its ID. Overridden by * {@link ServerSessionContext} to */ final NativeSslSession getSessionFromCache(byte[] sessionId) { if (sessionId == null) { return null; } // First, look in the in-memory cache. NativeSslSession session; synchronized (sessions) { session = sessions.get(new ByteArray(sessionId)); } if (session != null && session.isValid()) { if (session.isSingleUse()) { removeSession(session); } return session; } // Look in persistent cache. We don't currently delete sessions from the persistent // cache, so we may find a multi-use (aka TLS 1.2) session after having received and // then used up one or more single-use (aka TLS 1.3) sessions. return getSessionFromPersistentCache(sessionId); }
@Override public void onNewSessionEstablished(long sslSessionNativePtr) { try { // Increment the reference count to "take ownership" of the session resource. NativeCrypto.SSL_SESSION_up_ref(sslSessionNativePtr); // Create a native reference which will release the SSL_SESSION in its finalizer. // This constructor will only throw if the native pointer passed in is NULL, which // BoringSSL guarantees will not happen. NativeRef.SSL_SESSION ref = new SSL_SESSION(sslSessionNativePtr); NativeSslSession nativeSession = NativeSslSession.newInstance(ref, activeSession); // Cache the newly established session. AbstractSessionContext ctx = sessionContext(); ctx.cacheSession(nativeSession); } catch (Exception ignored) { // Ignore. } }
@Override public final void setSessionCacheSize(int size) throws IllegalArgumentException { if (size < 0) { throw new IllegalArgumentException("size < 0"); } int oldMaximum = maximumSize; maximumSize = size; // Trim cache to size if necessary. if (size < oldMaximum) { trimToSize(); } }
/** * Called for server sessions only. Retrieves the session by its ID. Overridden by * {@link ServerSessionContext} to */ final NativeSslSession getSessionFromCache(byte[] sessionId) { if (sessionId == null) { return null; } // First, look in the in-memory cache. NativeSslSession session; synchronized (sessions) { session = sessions.get(new ByteArray(sessionId)); } if (session != null && session.isValid()) { if (session.isSingleUse()) { removeSession(session); } return session; } // Look in persistent cache. We don't currently delete sessions from the persistent // cache, so we may find a multi-use (aka TLS 1.2) session after having received and // then used up one or more single-use (aka TLS 1.3) sessions. return getSessionFromPersistentCache(sessionId); }
@Override public void onNewSessionEstablished(long sslSessionNativePtr) { try { // Increment the reference count to "take ownership" of the session resource. NativeCrypto.SSL_SESSION_up_ref(sslSessionNativePtr); // Create a native reference which will release the SSL_SESSION in its finalizer. // This constructor will only throw if the native pointer passed in is NULL, which // BoringSSL guarantees will not happen. NativeRef.SSL_SESSION ref = new SSL_SESSION(sslSessionNativePtr); NativeSslSession nativeSession = NativeSslSession.newInstance(ref, activeSession); // Cache the newly established session. AbstractSessionContext ctx = sessionContext(); ctx.cacheSession(nativeSession); } catch (Exception ignored) { // Ignore. } }
@Override public final void setSessionCacheSize(int size) throws IllegalArgumentException { if (size < 0) { throw new IllegalArgumentException("size < 0"); } int oldMaximum = maximumSize; maximumSize = size; // Trim cache to size if necessary. if (size < oldMaximum) { trimToSize(); } }
@Override protected boolean removeEldestEntry( Map.Entry<ByteArray, NativeSslSession> eldest) { // NOTE: does not take into account any session that may have become // invalid. if (maximumSize > 0 && size() > maximumSize) { // Let the subclass know. onBeforeRemoveSession(eldest.getValue()); return true; } return false; } };
/** * Adds the given session to the cache. */ final void cacheSession(NativeSslSession session) { byte[] id = session.getId(); if (id == null || id.length == 0) { return; } synchronized (sessions) { ByteArray key = new ByteArray(id); if (sessions.containsKey(key)) { removeSession(sessions.get(key)); } // Let the subclass know. onBeforeAddSession(session); sessions.put(key, session); } }
@Override @SuppressWarnings("unused") // used by NativeCrypto.SSLHandshakeCallbacks / new_session_callback public final void onNewSessionEstablished(long sslSessionNativePtr) { try { // Increment the reference count to "take ownership" of the session resource. NativeCrypto.SSL_SESSION_up_ref(sslSessionNativePtr); // Create a native reference which will release the SSL_SESSION in its finalizer. // This constructor will only throw if the native pointer passed in is NULL, which // BoringSSL guarantees will not happen. NativeRef.SSL_SESSION ref = new SSL_SESSION(sslSessionNativePtr); NativeSslSession nativeSession = NativeSslSession.newInstance(ref, activeSession); // Cache the newly established session. AbstractSessionContext ctx = sessionContext(); ctx.cacheSession(nativeSession); } catch (Exception ignored) { // Ignore. } }
@Override boolean isValid() { long creationTimeMillis = getCreationTime(); // Use the minimum of the timeout from the context and the session. long timeoutMillis = Math.max(0, Math.min(context.getSessionTimeout(), NativeCrypto.SSL_SESSION_get_timeout(ref.address))) * 1000; return (System.currentTimeMillis() - timeoutMillis) < creationTimeMillis; }
/** * Makes sure cache size is < maximumSize. */ private void trimToSize() { synchronized (sessions) { int size = sessions.size(); if (size > maximumSize) { int removals = size - maximumSize; Iterator<NativeSslSession> i = sessions.values().iterator(); while (removals-- > 0) { NativeSslSession session = i.next(); onBeforeRemoveSession(session); i.remove(); } } } } }
@Override @SuppressWarnings("unused") // used by NativeCrypto.SSLHandshakeCallbacks / new_session_callback public final void onNewSessionEstablished(long sslSessionNativePtr) { try { // Increment the reference count to "take ownership" of the session resource. NativeCrypto.SSL_SESSION_up_ref(sslSessionNativePtr); // Create a native reference which will release the SSL_SESSION in its finalizer. // This constructor will only throw if the native pointer passed in is NULL, which // BoringSSL guarantees will not happen. NativeRef.SSL_SESSION ref = new SSL_SESSION(sslSessionNativePtr); NativeSslSession nativeSession = NativeSslSession.newInstance(ref, activeSession); // Cache the newly established session. AbstractSessionContext ctx = sessionContext(); ctx.cacheSession(nativeSession); } catch (Exception ignored) { // Ignore. } }
@Override protected boolean removeEldestEntry( Map.Entry<ByteArray, NativeSslSession> eldest) { // NOTE: does not take into account any session that may have become // invalid. if (maximumSize > 0 && size() > maximumSize) { // Let the subclass know. onBeforeRemoveSession(eldest.getValue()); return true; } return false; } };
/** * Removes the given session from the cache. */ final void removeSession(NativeSslSession session) { byte[] id = session.getId(); if (id == null || id.length == 0) { return; } onBeforeRemoveSession(session); ByteArray key = new ByteArray(id); synchronized (sessions) { sessions.remove(key); } }
/** * Removes the given session from the cache. */ final void removeSession(NativeSslSession session) { byte[] id = session.getId(); if (id == null || id.length == 0) { return; } onBeforeRemoveSession(session); ByteArray key = new ByteArray(id); synchronized (sessions) { sessions.remove(key); } }
@Override public final void setSessionTimeout(int seconds) throws IllegalArgumentException { if (seconds < 0) { throw new IllegalArgumentException("seconds < 0"); } synchronized (sessions) { // Set the timeout on this context. timeout = seconds; // setSessionTimeout(0) is defined to remove the timeout, but passing 0 // to SSL_CTX_set_timeout in BoringSSL sets it to the default timeout instead. // Pass INT_MAX seconds (68 years), since that's equivalent for practical purposes. if (seconds > 0) { NativeCrypto.SSL_CTX_set_timeout(sslCtxNativePointer, this, seconds); } else { NativeCrypto.SSL_CTX_set_timeout(sslCtxNativePointer, this, Integer.MAX_VALUE); } Iterator<NativeSslSession> i = sessions.values().iterator(); while (i.hasNext()) { NativeSslSession session = i.next(); // SSLSession's know their context and consult the // timeout as part of their validity condition. if (!session.isValid()) { // Let the subclass know. onBeforeRemoveSession(session); i.remove(); } } } }
@Override public final void setSessionTimeout(int seconds) throws IllegalArgumentException { if (seconds < 0) { throw new IllegalArgumentException("seconds < 0"); } synchronized (sessions) { // Set the timeout on this context. timeout = seconds; // setSessionTimeout(0) is defined to remove the timeout, but passing 0 // to SSL_CTX_set_timeout in BoringSSL sets it to the default timeout instead. // Pass INT_MAX seconds (68 years), since that's equivalent for practical purposes. if (seconds > 0) { NativeCrypto.SSL_CTX_set_timeout(sslCtxNativePointer, this, seconds); } else { NativeCrypto.SSL_CTX_set_timeout(sslCtxNativePointer, this, Integer.MAX_VALUE); } Iterator<NativeSslSession> i = sessions.values().iterator(); while (i.hasNext()) { NativeSslSession session = i.next(); // SSLSession's know their context and consult the // timeout as part of their validity condition. if (!session.isValid()) { // Let the subclass know. onBeforeRemoveSession(session); i.remove(); } } } }