/******************************************************************************* * Copyright (c) 2011 Intalio, Inc. * ====================================================================== * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * and Apache License v2.0 which accompanies this distribution. * * The Eclipse Public License is available at * http://www.eclipse.org/legal/epl-v10.html * * The Apache License v2.0 is available at * http://www.opensource.org/licenses/apache2.0.php * * You may elect to redistribute this code under either of these licenses. *******************************************************************************/ package org.eclipse.jetty.websocket; import java.io.IOException; import java.net.URI; import java.util.Arrays; import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; import javax.servlet.http.HttpServletRequest; import org.eclipse.jetty.server.Server; import org.eclipse.jetty.server.ssl.SslSelectChannelConnector; import org.eclipse.jetty.toolchain.test.MavenTestingUtils; import org.eclipse.jetty.util.ssl.SslContextFactory; import org.eclipse.jetty.util.thread.QueuedThreadPool; import org.junit.After; import org.junit.Assert; import org.junit.Test; public class WebSocketOverSSLTest { private Server _server; private int _port; private QueuedThreadPool _threadPool; private WebSocketClientFactory _wsFactory; private WebSocket.Connection _connection; private void startServer(final WebSocket webSocket) throws Exception { _server = new Server(); SslSelectChannelConnector connector = new SslSelectChannelConnector(); _server.addConnector(connector); SslContextFactory cf = connector.getSslContextFactory(); cf.setKeyStorePath(MavenTestingUtils.getTestResourceFile("keystore").getAbsolutePath()); cf.setKeyStorePassword("storepwd"); cf.setKeyManagerPassword("keypwd"); _server.setHandler(new WebSocketHandler() { public WebSocket doWebSocketConnect(HttpServletRequest request, String protocol) { return webSocket; } }); _server.start(); _port = connector.getLocalPort(); } private void startClient(final WebSocket webSocket) throws Exception { Assert.assertTrue(_server.isStarted()); _threadPool = new QueuedThreadPool(); _threadPool.setName("wsc-" + _threadPool.getName()); _threadPool.start(); _wsFactory = new WebSocketClientFactory(_threadPool, new ZeroMaskGen()); SslContextFactory cf = _wsFactory.getSslContextFactory(); cf.setKeyStorePath(MavenTestingUtils.getTestResourceFile("keystore").getAbsolutePath()); cf.setKeyStorePassword("storepwd"); cf.setKeyManagerPassword("keypwd"); _wsFactory.start(); WebSocketClient client = new WebSocketClient(_wsFactory); _connection = client.open(new URI("wss://localhost:" + _port), webSocket).get(5, TimeUnit.SECONDS); } @After public void destroy() throws Exception { if (_connection != null) _connection.close(); if (_wsFactory != null) _wsFactory.stop(); if (_threadPool != null) _threadPool.stop(); if (_server != null) { _server.stop(); _server.join(); } } @Test public void testWebSocketOverSSL() throws Exception { final String message = "message"; final CountDownLatch serverLatch = new CountDownLatch(1); startServer(new WebSocket.OnTextMessage() { private Connection connection; public void onOpen(Connection connection) { this.connection = connection; } public void onMessage(String data) { try { Assert.assertEquals(message, data); connection.sendMessage(data); serverLatch.countDown(); } catch (IOException x) { x.printStackTrace(); } } public void onClose(int closeCode, String message) { } }); final CountDownLatch clientLatch = new CountDownLatch(1); startClient(new WebSocket.OnTextMessage() { public void onOpen(Connection connection) { } public void onMessage(String data) { Assert.assertEquals(message, data); clientLatch.countDown(); } public void onClose(int closeCode, String message) { } }); _connection.sendMessage(message); Assert.assertTrue(serverLatch.await(5, TimeUnit.SECONDS)); Assert.assertTrue(clientLatch.await(5, TimeUnit.SECONDS)); } @Test public void testManyMessages() throws Exception { startServer(new WebSocket.OnTextMessage() { private Connection connection; public void onOpen(Connection connection) { this.connection = connection; } public void onMessage(String data) { try { connection.sendMessage(data); } catch (IOException x) { x.printStackTrace(); } } public void onClose(int closeCode, String message) { } }); int count = 1000; final CountDownLatch clientLatch = new CountDownLatch(count); startClient(new WebSocket.OnTextMessage() { public void onOpen(Connection connection) { } public void onMessage(String data) { clientLatch.countDown(); } public void onClose(int closeCode, String message) { } }); char[] chars = new char[256]; Arrays.fill(chars, 'x'); String message = new String(chars); for (int i = 0; i < count; ++i) _connection.sendMessage(message); Assert.assertTrue(clientLatch.await(20, TimeUnit.SECONDS)); // While messages may have all arrived, the SSL close alert // may be in the way so give some time for it to be processed. TimeUnit.SECONDS.sleep(1); } }