package org.httpkit.client; import javax.net.ssl.*; import java.net.InetSocketAddress; import java.nio.ByteBuffer; import java.nio.channels.SocketChannel; /** * Created with IntelliJ IDEA. * User: feng * Date: 4/11/13 * Time: 2:09 PM * To change this template use File | Settings | File Templates. */ public class SSLTest { private static final SSLContext CLIENT_CONTEXT; static { SSLContext clientContext = null; try { // SSLContext.getInstance() clientContext = SSLContext.getDefault(); // clientContext = SSLContext.getInstance("TLS"); // clientContext.init(null, TrustManagerFactory.getTrustManagers(), // null); } catch (Exception e) { throw new Error( "Failed to initialize the client-side SSLContext", e); } CLIENT_CONTEXT = clientContext; } public static void main(String[] args) throws Exception { SSLEngine engine = CLIENT_CONTEXT.createSSLEngine(); engine.setUseClientMode(true); // Create a nonblocking socket channel SocketChannel socketChannel = SocketChannel.open(); socketChannel.configureBlocking(true); socketChannel.connect(new InetSocketAddress("google.com", 443)); // Complete connection // int i = 0; while (!socketChannel.finishConnect()) { // System.out.println("----------" + i++); Thread.sleep(50); // do something until connect completed } // Create byte buffers to use for holding application and encoded data SSLSession session = engine.getSession(); ByteBuffer myNetData = ByteBuffer.allocate(session.getPacketBufferSize()); ByteBuffer peerAppData = ByteBuffer.allocate(session.getApplicationBufferSize()); ByteBuffer peerNetData = ByteBuffer.allocate(session.getPacketBufferSize()); peerNetData.limit(0); ByteBuffer myAppData = ByteBuffer.wrap(("GET / HTTP/1.1\r\nHost: \r\n\r\n").getBytes()); engine.beginHandshake(); SSLEngineResult.HandshakeStatus hs = engine.getHandshakeStatus(); while (hs != SSLEngineResult.HandshakeStatus.FINISHED && hs != SSLEngineResult.HandshakeStatus.NOT_HANDSHAKING) { System.out.println("hs status: " + hs); switch (hs) { case NEED_TASK: Runnable runnable; while ((runnable = engine.getDelegatedTask()) != null) { System.out.println("get task " + runnable); runnable.run(); } break; case NEED_UNWRAP: if (!peerNetData.hasRemaining()) { peerNetData.clear(); int read = socketChannel.read(peerNetData); System.out.println("read: " + read + "\t" + peerNetData); peerNetData.flip(); } SSLEngineResult status = engine.unwrap(peerNetData, peerAppData); // peerNetData.compact(); System.out.println("unwrap: " + status); switch (status.getStatus()) { case BUFFER_UNDERFLOW: peerNetData.compact(); // peerNetData.flip(); int read = socketChannel.read(peerNetData); System.out.println("flip read: " + read + "\t" + peerNetData); peerNetData.flip(); break; } break; case NEED_WRAP: myNetData.clear(); SSLEngineResult wrapStatus = engine.wrap(myAppData, myNetData); System.out.println("wrap: " + wrapStatus); myNetData.flip(); while (myNetData.hasRemaining()) { socketChannel.write(myNetData); } break; } hs = engine.getHandshakeStatus(); } // https://raw.github.com/http-kit/scale-clojure-web-app/master/results/600k/heap_usage.png for (int i = 0; i < 5; i++) { myNetData.clear(); peerAppData.clear(); myAppData = ByteBuffer.wrap(("GET / HTTP/1.1\r\nHost: www.google.co.jp\r\n\r\n").getBytes()); SSLEngineResult wrapStatus = engine.wrap(myAppData, myNetData); // System.out.println("---------wrap: " + wrapStatus); myNetData.flip(); while (myNetData.hasRemaining()) { socketChannel.write(myNetData); } peerNetData.clear(); int read = socketChannel.read(peerNetData); // System.out.println("-------read: " + read + "\t" + peerNetData); peerNetData.flip(); // Exception in thread "main" javax.net.ssl.SSLException: bad record MAC SSLEngineResult status = engine.unwrap(peerNetData, peerAppData); while (status.getStatus() != SSLEngineResult.Status.OK) { // System.out.println("-------unwrap: " + status); peerNetData.compact(); read = socketChannel.read(peerNetData); System.out.println("-------read: " + read + "\t" + peerNetData); peerNetData.flip(); status = engine.unwrap(peerNetData, peerAppData); } peerAppData.flip(); System.out.println(peerAppData); byte[] data = new byte[peerAppData.remaining()]; peerAppData.get(data); System.out.println(new String(data)); // peerNetData.compact(); } // Do initial handshake // doHandleShake2(socketChannel, engine, myNetData, peerNetData); } }