/* * Copyright (C) 2010 The Android Open Source Project * * Licensed 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 libcore.javax.net.ssl; import java.util.concurrent.Callable; import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.Future; import java.util.concurrent.TimeUnit; import javax.net.ssl.SSLSocket; /** * TestSSLSocketPair is a convenience class for other tests that want * a pair of connected and handshaked client and server SSLSockets for * testing. */ public final class TestSSLSocketPair { public final TestSSLContext c; public final SSLSocket server; public final SSLSocket client; private TestSSLSocketPair (TestSSLContext c, SSLSocket server, SSLSocket client) { this.c = c; this.server = server; this.client = client; } public void close() { c.close(); try { server.close(); client.close(); } catch (Exception e) { throw new RuntimeException(e); } } /** * based on test_SSLSocket_startHandshake */ public static TestSSLSocketPair create () { TestSSLContext c = TestSSLContext.create(); SSLSocket[] sockets = connect(c, null, null); return new TestSSLSocketPair(c, sockets[0], sockets[1]); } /** * Create a new connected server/client socket pair within a * existing SSLContext. Optionally specify clientCipherSuites to * allow forcing new SSLSession to test SSLSessionContext * caching. Optionally specify serverCipherSuites for testing * cipher suite negotiation. */ public static SSLSocket[] connect (final TestSSLContext context, final String[] clientCipherSuites, final String[] serverCipherSuites) { try { final SSLSocket client = (SSLSocket) context.clientContext.getSocketFactory().createSocket(context.host, context.port); final SSLSocket server = (SSLSocket) context.serverSocket.accept(); ExecutorService executor = Executors.newFixedThreadPool(2); Future s = executor.submit(new Callable<Void>() { public Void call() throws Exception { if (serverCipherSuites != null) { server.setEnabledCipherSuites(serverCipherSuites); } server.startHandshake(); return null; } }); Future c = executor.submit(new Callable<Void>() { public Void call() throws Exception { if (clientCipherSuites != null) { client.setEnabledCipherSuites(clientCipherSuites); } client.startHandshake(); return null; } }); executor.shutdown(); // catch client and server exceptions separately so we can // potentially log both. Exception serverException; try { s.get(30, TimeUnit.SECONDS); serverException = null; } catch (Exception e) { serverException = e; e.printStackTrace(); } Exception clientException; try { c.get(30, TimeUnit.SECONDS); clientException = null; } catch (Exception e) { clientException = e; e.printStackTrace(); } if (serverException != null) { throw serverException; } if (clientException != null) { throw clientException; } return new SSLSocket[] { server, client }; } catch (RuntimeException e) { throw e; } catch (Exception e) { throw new RuntimeException(e); } } }