/* * Copyright (C) 2015 SoftIndex LLC. * * 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 io.datakernel.https; import ch.qos.logback.classic.Level; import ch.qos.logback.classic.Logger; import io.datakernel.async.*; import io.datakernel.dns.AsyncDnsClient; import io.datakernel.eventloop.Eventloop; import io.datakernel.http.*; import org.junit.Test; import org.slf4j.LoggerFactory; import javax.net.ssl.KeyManager; import javax.net.ssl.SSLContext; import javax.net.ssl.TrustManager; import java.io.File; import java.net.InetAddress; import java.security.SecureRandom; import java.util.concurrent.ExecutorService; import static io.datakernel.async.AsyncRunnables.runInParallel; import static io.datakernel.bytebuf.ByteBufPool.*; import static io.datakernel.bytebuf.ByteBufStrings.decodeAscii; import static io.datakernel.bytebuf.ByteBufStrings.wrapAscii; import static io.datakernel.eventloop.FatalErrorHandlers.rethrowOnAnyError; import static io.datakernel.http.HttpRequest.post; import static io.datakernel.http.HttpResponse.ok200; import static io.datakernel.http.HttpUtils.inetAddress; import static io.datakernel.https.SslUtils.*; import static java.util.Arrays.asList; import static java.util.concurrent.Executors.newCachedThreadPool; import static junit.framework.TestCase.assertEquals; public class TestHttpsClientServer { private static final int PORT = 5590; private static final int SSL_PORT = 5591; static { Logger root = (Logger) LoggerFactory.getLogger(Logger.ROOT_LOGGER_NAME); root.setLevel(Level.TRACE); //System.setProperty("javax.net.debug", "all"); } private KeyManager[] keyManagers = createKeyManagers(new File("./src/test/resources/keystore.jks"), "testtest", "testtest"); private TrustManager[] trustManagers = createTrustManagers(new File("./src/test/resources/truststore.jks"), "testtest"); private AsyncServlet bobServlet = new AsyncServlet() { @Override public void serve(HttpRequest request, ResultCallback<HttpResponse> callback) { callback.setResult(ok200().withBody(wrapAscii("Hello, I am Bob!"))); } }; private Eventloop eventloop = Eventloop.create().withFatalErrorHandler(rethrowOnAnyError()); private ExecutorService executor = newCachedThreadPool(); private SSLContext context = createSslContext("TLSv1.2", keyManagers, trustManagers, new SecureRandom()); public TestHttpsClientServer() throws Exception { } public static final InetAddress GOOGLE_PUBLIC_DNS = inetAddress("8.8.8.8"); @Test public void testClientServerInteraction() throws Exception { final AsyncHttpServer server = AsyncHttpServer.create(eventloop, bobServlet) .withSslListenPort(createSslContext("TLSv1.2", keyManagers, trustManagers, new SecureRandom()), executor, SSL_PORT); final AsyncDnsClient dnsClient = AsyncDnsClient.create(eventloop) .withTimeout(500) .withDnsServerAddress(GOOGLE_PUBLIC_DNS); final AsyncHttpClient client = AsyncHttpClient.create(eventloop) .withConnectTimeout(500) .withDnsClient(dnsClient) .withSslEnabled(createSslContext("TLSv1.2", keyManagers, trustManagers, new SecureRandom()), executor); HttpRequest request = post("https://127.0.0.1:" + SSL_PORT).withBody(wrapAscii("Hello, I am Alice!")); final ResultCallbackFuture<String> callback = ResultCallbackFuture.create(); server.listen(); client.send(request, new ResultCallback<HttpResponse>() { @Override public void onResult(HttpResponse result) { callback.setResult(decodeAscii(result.getBody())); server.close(IgnoreCompletionCallback.create()); client.stop(IgnoreCompletionCallback.create()); } @Override public void onException(Exception e) { callback.setException(e); server.close(IgnoreCompletionCallback.create()); client.stop(IgnoreCompletionCallback.create()); } }); eventloop.run(); executor.shutdown(); assertEquals("Hello, I am Bob!", callback.get()); assertEquals(getPoolItemsString(), getCreatedItems(), getPoolItems()); } @Test public void testServesTwoPortsSimultaneously() throws Exception { final AsyncHttpServer server = AsyncHttpServer.create(eventloop, bobServlet) .withSslListenPort(context, executor, SSL_PORT) .withListenPort(PORT); final AsyncDnsClient dnsClient = AsyncDnsClient.create(eventloop) .withTimeout(500) .withDnsServerAddress(GOOGLE_PUBLIC_DNS); final AsyncHttpClient client = AsyncHttpClient.create(eventloop) .withDnsClient(dnsClient) .withConnectTimeout(500) .withSslEnabled(context, executor); final HttpRequest httpsRequest = post("https://127.0.0.1:" + SSL_PORT).withBody(wrapAscii("Hello, I am Alice!")); final HttpRequest httpRequest = post("http://127.0.0.1:" + PORT).withBody(wrapAscii("Hello, I am Alice!")); final ResultCallbackFuture<String> callbackHttps = ResultCallbackFuture.create(); final ResultCallbackFuture<String> callbackHttp = ResultCallbackFuture.create(); server.listen(); runInParallel(eventloop, asList( new AsyncRunnable() { @Override public void run(final CompletionCallback callback) { client.send(httpsRequest, new AssertingResultCallback<HttpResponse>() { @Override public void onResult(HttpResponse result) { callbackHttps.setResult(decodeAscii(result.getBody())); callback.setComplete(); } }); } }, new AsyncRunnable() { @Override public void run(final CompletionCallback callback) { client.send(httpRequest, new AssertingResultCallback<HttpResponse>() { @Override public void onResult(HttpResponse result) { callbackHttp.setResult(decodeAscii(result.getBody())); callback.setComplete(); } }); } } )).run(new AssertingCompletionCallback() { @Override protected void onComplete() { server.close(IgnoreCompletionCallback.create()); client.stop(IgnoreCompletionCallback.create()); } }); eventloop.run(); executor.shutdown(); assertEquals(callbackHttp.get(), callbackHttps.get()); assertEquals(getPoolItemsString(), getCreatedItems(), getPoolItems()); } }