1f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 2f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Copyright (C) 2009 The Android Open Source Project 3f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 4f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License"); 5f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * you may not use this file except in compliance with the License. 6f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * You may obtain a copy of the License at 7f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 8f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * http://www.apache.org/licenses/LICENSE-2.0 9f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 10f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Unless required by applicable law or agreed to in writing, software 11f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS, 12f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * See the License for the specific language governing permissions and 14f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * limitations under the License. 15f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 16f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 17f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectpackage org.apache.harmony.xnet.provider.jsse; 18f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 19f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport java.util.LinkedHashMap; 20f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport java.util.Map; 21f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport java.util.Iterator; 22f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport java.util.ArrayList; 23f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport java.util.Arrays; 24f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 25f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport javax.net.ssl.SSLSession; 26f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 27f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/** 28f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Caches server sessions. Indexes by session ID. Users typically look up 29f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * sessions using the ID provided by an SSL client. 30f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 31f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectpublic class ServerSessionContext extends AbstractSessionContext { 32f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 33f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* 34f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * TODO: Expire timed-out sessions more pro-actively. 35f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 36f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 37f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project private final Map<ByteArray, SSLSession> sessions 38f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project = new LinkedHashMap<ByteArray, SSLSession>() { 39f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project @Override 40f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project protected boolean removeEldestEntry( 41f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project Map.Entry<ByteArray, SSLSession> eldest) { 42f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return maximumSize > 0 && size() > maximumSize; 43f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 44f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project }; 45f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 46f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project private final SSLServerSessionCache persistentCache; 47f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 48f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project public ServerSessionContext(SSLParameters parameters, 49f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project SSLServerSessionCache persistentCache) { 50f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project super(parameters, 100, 0); 51f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project this.persistentCache = persistentCache; 52f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 53f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 54f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project Iterator<SSLSession> sessionIterator() { 55f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project synchronized (sessions) { 56f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project SSLSession[] array = sessions.values().toArray( 57f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project new SSLSession[sessions.size()]); 58f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return Arrays.asList(array).iterator(); 59f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 60f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 61f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 62f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project void trimToSize() { 63f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project synchronized (sessions) { 64f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int size = sessions.size(); 65f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (size > maximumSize) { 66f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int removals = size - maximumSize; 67f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project Iterator<SSLSession> i = sessions.values().iterator(); 68f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project do { 69f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project i.next(); 70f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project i.remove(); 71f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } while (--removals > 0); 72f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 73f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 74f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 75f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 76f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project public void setSessionTimeout(int seconds) 77f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project throws IllegalArgumentException { 78f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (seconds < 0) { 79f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project throw new IllegalArgumentException("seconds < 0"); 80f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 81f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project timeout = seconds; 82f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 83f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 84f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project public SSLSession getSession(byte[] sessionId) { 85f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project ByteArray key = new ByteArray(sessionId); 86f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project synchronized (sessions) { 87f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project SSLSession session = sessions.get(key); 88f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (session != null) { 89f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return session; 90f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 91f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 92f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 93f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // Check persistent cache. 94f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (persistentCache != null) { 95f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project byte[] data = persistentCache.getSessionData(sessionId); 96f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (data != null) { 97f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project SSLSession session = toSession(data, null, -1); 98f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (session != null) { 99f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project synchronized (sessions) { 100f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project sessions.put(key, session); 101f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 102f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return session; 103f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 104f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 105f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 106f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 107f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return null; 108f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 109f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 110f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project void putSession(SSLSession session) { 111f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project ByteArray key = new ByteArray(session.getId()); 112f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project synchronized (sessions) { 113f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project sessions.put(key, session); 114f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 115f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 116f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // TODO: In background thread. 117f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (persistentCache != null) { 118f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project byte[] data = toBytes(session); 119f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (data != null) { 120f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project persistentCache.putSessionData(session, data); 121f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 122f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 123f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 124f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} 125