From 4ea8d82b33128fc9bf12195008a26a14841a4828 Mon Sep 17 00:00:00 2001 From: Dan Noguerol Date: Wed, 14 May 2014 17:38:15 -0600 Subject: [PATCH 01/17] Added support for HTTPS connections. Added support for custom HTTP request headers. Added EventSource state updates for OPEN and CLOSED. --- pom.xml | 57 ++-- .../eventsource/client/EventSource.java | 40 ++- .../impl/netty/EventSourceChannelHandler.java | 10 + .../impl/netty/ssl/SslContextFactory.java | 92 +++++ .../client/impl/netty/ssl/SslKeyStore.java | 313 ++++++++++++++++++ .../netty/ssl/SslTrustManagerFactory.java | 79 +++++ 6 files changed, 554 insertions(+), 37 deletions(-) create mode 100644 src/main/java/com/github/eventsource/client/impl/netty/ssl/SslContextFactory.java create mode 100644 src/main/java/com/github/eventsource/client/impl/netty/ssl/SslKeyStore.java create mode 100644 src/main/java/com/github/eventsource/client/impl/netty/ssl/SslTrustManagerFactory.java diff --git a/pom.xml b/pom.xml index 1f60e61..c6ead51 100644 --- a/pom.xml +++ b/pom.xml @@ -1,17 +1,12 @@ 4.0.0 - com.github.aslakhellesoy + com.whizzosoftware eventsource-client ${project.artifactId} A Java EventSource Client - http://aslakhellesoy.github.com/eventsource-java - 0.1.2.1 + http://whizzosoftware.github.com/eventsource-java + 0.1.3 jar - - org.sonatype.oss - oss-parent - 6 - BSD License @@ -19,18 +14,13 @@ repo - - scm:git:git://github.com/aslakhellesoy/eventsource-java.git - scm:git:git@github.com:aslakhellesoy/eventsource-java.git - git://github.com/aslakhellesoy/eventsource-java.git - - - - repository.jboss.org - http://repository.jboss.org/nexus/content/groups/public/ - - + + org.slf4j + slf4j-api + 1.7.6 + compile + org.jboss.netty netty @@ -67,23 +57,18 @@ 1.6 - - org.apache.maven.plugins - maven-gpg-plugin - 1.1 - - true - - - - sign-artifacts - verify - - sign - - - - + + + nx-releases + Nexus Releases + ${nexus.releases.url} + + + nx-snapshots + Nexus Snapshots + ${nexus.snapshots.url} + + diff --git a/src/main/java/com/github/eventsource/client/EventSource.java b/src/main/java/com/github/eventsource/client/EventSource.java index 17d8cce..a54723d 100644 --- a/src/main/java/com/github/eventsource/client/EventSource.java +++ b/src/main/java/com/github/eventsource/client/EventSource.java @@ -2,6 +2,7 @@ import com.github.eventsource.client.impl.AsyncEventSourceHandler; import com.github.eventsource.client.impl.netty.EventSourceChannelHandler; +import com.github.eventsource.client.impl.netty.ssl.SslContextFactory; import org.jboss.netty.bootstrap.ClientBootstrap; import org.jboss.netty.channel.ChannelFuture; import org.jboss.netty.channel.ChannelPipeline; @@ -12,13 +13,15 @@ import org.jboss.netty.handler.codec.frame.Delimiters; import org.jboss.netty.handler.codec.http.HttpRequestEncoder; import org.jboss.netty.handler.codec.string.StringDecoder; +import org.jboss.netty.handler.ssl.SslHandler; +import javax.net.ssl.SSLEngine; import java.net.InetSocketAddress; import java.net.URI; import java.util.concurrent.Executor; import java.util.concurrent.Executors; -public class EventSource { +public class EventSource implements EventSourceHandler { public static final long DEFAULT_RECONNECTION_TIME_MILLIS = 2000; public static final int CONNECTING = 0; @@ -27,6 +30,7 @@ public class EventSource { private final ClientBootstrap bootstrap; private final EventSourceChannelHandler clientHandler; + private final EventSourceHandler eventSourceHandler; private int readyState; @@ -44,6 +48,8 @@ public class EventSource { * @see #close() */ public EventSource(Executor executor, long reconnectionTimeMillis, final URI uri, EventSourceHandler eventSourceHandler) { + this.eventSourceHandler = eventSourceHandler; + bootstrap = new ClientBootstrap( new NioClientSocketChannelFactory( Executors.newSingleThreadExecutor(), @@ -55,6 +61,13 @@ public EventSource(Executor executor, long reconnectionTimeMillis, final URI uri bootstrap.setPipelineFactory(new ChannelPipelineFactory() { public ChannelPipeline getPipeline() throws Exception { ChannelPipeline pipeline = Channels.pipeline(); + + if (uri.getScheme().equalsIgnoreCase("https")) { + SSLEngine engine = SslContextFactory.getClientContext().createSSLEngine(); + engine.setUseClientMode(true); + pipeline.addLast("ssl", new SslHandler(engine)); + } + pipeline.addLast("line", new DelimiterBasedFrameDecoder(Integer.MAX_VALUE, Delimiters.lineDelimiter())); pipeline.addLast("string", new StringDecoder()); @@ -73,17 +86,26 @@ public EventSource(URI uri, EventSourceHandler eventSourceHandler) { this(Executors.newSingleThreadExecutor(), DEFAULT_RECONNECTION_TIME_MILLIS, uri, eventSourceHandler); } + public void setCustomRequestHeader(String name, String value) { + clientHandler.setCustomRequestHeader(name, value); + } + public ChannelFuture connect() { readyState = CONNECTING; return bootstrap.connect(); } + public boolean isConnected() { + return (readyState == OPEN); + } + /** * Close the connection * * @return self */ public EventSource close() { + readyState = CLOSED; clientHandler.close(); return this; } @@ -98,4 +120,20 @@ public EventSource join() throws InterruptedException { clientHandler.join(); return this; } + + @Override + public void onConnect() throws Exception { + readyState = OPEN; + eventSourceHandler.onConnect(); + } + + @Override + public void onMessage(String event, MessageEvent message) throws Exception { + eventSourceHandler.onMessage(event, message); + } + + @Override + public void onError(Throwable t) { + eventSourceHandler.onError(t); + } } diff --git a/src/main/java/com/github/eventsource/client/impl/netty/EventSourceChannelHandler.java b/src/main/java/com/github/eventsource/client/impl/netty/EventSourceChannelHandler.java index 6ad7d7b..809b70f 100644 --- a/src/main/java/com/github/eventsource/client/impl/netty/EventSourceChannelHandler.java +++ b/src/main/java/com/github/eventsource/client/impl/netty/EventSourceChannelHandler.java @@ -18,6 +18,8 @@ import java.net.ConnectException; import java.net.URI; +import java.util.HashMap; +import java.util.Map; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicBoolean; import java.util.regex.Matcher; @@ -31,6 +33,7 @@ public class EventSourceChannelHandler extends SimpleChannelUpstreamHandler impl private final ClientBootstrap bootstrap; private final URI uri; private final EventStreamParser messageDispatcher; + private final Map customRequestHeaders = new HashMap(); private final Timer timer = new HashedWheelTimer(); private Channel channel; @@ -65,6 +68,9 @@ public void channelConnected(ChannelHandlerContext ctx, ChannelStateEvent e) thr if (lastEventId != null) { request.addHeader("Last-Event-ID", lastEventId); } + for (String name : customRequestHeaders.keySet()) { + request.addHeader(name, customRequestHeaders.get(name)); + } e.getChannel().write(request); channel = e.getChannel(); } @@ -150,6 +156,10 @@ public EventSourceChannelHandler join() throws InterruptedException { return this; } + public void setCustomRequestHeader(String name, String value) { + customRequestHeaders.put(name, value); + } + private void reconnect() { if(!reconnecting.get()) { reconnecting.set(true); diff --git a/src/main/java/com/github/eventsource/client/impl/netty/ssl/SslContextFactory.java b/src/main/java/com/github/eventsource/client/impl/netty/ssl/SslContextFactory.java new file mode 100644 index 0000000..48ec8dc --- /dev/null +++ b/src/main/java/com/github/eventsource/client/impl/netty/ssl/SslContextFactory.java @@ -0,0 +1,92 @@ +/* + * Copyright 2012 The Netty Project + * + * The Netty Project licenses this file to you 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 com.github.eventsource.client.impl.netty.ssl; + +import javax.net.ssl.KeyManagerFactory; +import javax.net.ssl.SSLContext; +import java.security.KeyStore; +import java.security.Security; + +/** + * Creates a bogus {@link SSLContext}. A client-side context created by this + * factory accepts any certificate even if it is invalid. A server-side context + * created by this factory sends a bogus certificate defined in {@link SecureChatKeyStore}. + *

+ * You will have to create your context differently in a real world application. + * + *

Client Certificate Authentication

+ * + * To enable client certificate authentication: + *
    + *
  • Enable client authentication on the server side by calling + * {@link SSLEngine#setNeedClientAuth(boolean)} before creating + * {@link SslHandler}.
  • + *
  • When initializing an {@link SSLContext} on the client side, + * specify the {@link KeyManager} that contains the client certificate as + * the first argument of {@link SSLContext#init(KeyManager[], TrustManager[], SecureRandom)}.
  • + *
  • When initializing an {@link SSLContext} on the server side, + * specify the proper {@link TrustManager} as the second argument of + * {@link SSLContext#init(KeyManager[], TrustManager[], SecureRandom)} + * to validate the client certificate.
  • + *
+ */ +public class SslContextFactory { + private static final String PROTOCOL = "TLS"; + private static final SSLContext SERVER_CONTEXT; + private static final SSLContext CLIENT_CONTEXT; + + static { + String algorithm = Security.getProperty("ssl.KeyManagerFactory.algorithm"); + if (algorithm == null) { + algorithm = "SunX509"; + } + + SSLContext serverContext = null; + SSLContext clientContext = null; + try { + KeyStore ks = KeyStore.getInstance("JKS"); + ks.load(SslKeyStore.asInputStream(), SslKeyStore.getKeyStorePassword()); + + // Set up key manager factory to use our key store + KeyManagerFactory kmf = KeyManagerFactory.getInstance(algorithm); + kmf.init(ks, SslKeyStore.getCertificatePassword()); + + // Initialize the SSLContext to work with our key managers. + serverContext = SSLContext.getInstance(PROTOCOL); + serverContext.init(kmf.getKeyManagers(), null, null); + } catch (Exception e) { + throw new Error("Failed to initialize the server-side SSLContext", e); + } + + try { + clientContext = SSLContext.getInstance(PROTOCOL); + clientContext.init(null, SslTrustManagerFactory.getTrustManagers(), null); + } catch (Exception e) { + throw new Error("Failed to initialize the client-side SSLContext", e); + } + + SERVER_CONTEXT = serverContext; + CLIENT_CONTEXT = clientContext; + } + + public static SSLContext getServerContext() { + return SERVER_CONTEXT; + } + + public static SSLContext getClientContext() { + return CLIENT_CONTEXT; + } +} diff --git a/src/main/java/com/github/eventsource/client/impl/netty/ssl/SslKeyStore.java b/src/main/java/com/github/eventsource/client/impl/netty/ssl/SslKeyStore.java new file mode 100644 index 0000000..63a0347 --- /dev/null +++ b/src/main/java/com/github/eventsource/client/impl/netty/ssl/SslKeyStore.java @@ -0,0 +1,313 @@ +/* + * Copyright 2012 The Netty Project + * + * The Netty Project licenses this file to you 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 com.github.eventsource.client.impl.netty.ssl; + +import java.io.ByteArrayInputStream; +import java.io.InputStream; + +/** + * A bogus key store which provides all the required information to + * create an example SSL connection. + * + * To generate a bogus key store: + *
+ * keytool  -genkey -alias securechat -keysize 2048 -validity 36500
+ *          -keyalg RSA -dname "CN=securechat"
+ *          -keypass secret -storepass secret
+ *          -keystore cert.jks
+ * 
+ */ +public class SslKeyStore { + private static final short[] DATA = { + 0xfe, 0xed, 0xfe, 0xed, 0x00, 0x00, 0x00, 0x02, + 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x07, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, + 0x65, 0x00, 0x00, 0x01, 0x1a, 0x9f, 0x57, 0xa5, + 0x27, 0x00, 0x00, 0x01, 0x9a, 0x30, 0x82, 0x01, + 0x96, 0x30, 0x0e, 0x06, 0x0a, 0x2b, 0x06, 0x01, + 0x04, 0x01, 0x2a, 0x02, 0x11, 0x01, 0x01, 0x05, + 0x00, 0x04, 0x82, 0x01, 0x82, 0x48, 0x6d, 0xcf, + 0x16, 0xb5, 0x50, 0x95, 0x36, 0xbf, 0x47, 0x27, + 0x50, 0x58, 0x0d, 0xa2, 0x52, 0x7e, 0x25, 0xab, + 0x14, 0x1a, 0x26, 0x5e, 0x2d, 0x8a, 0x23, 0x90, + 0x60, 0x7f, 0x12, 0x20, 0x56, 0xd1, 0x43, 0xa2, + 0x6b, 0x47, 0x5d, 0xed, 0x9d, 0xd4, 0xe5, 0x83, + 0x28, 0x89, 0xc2, 0x16, 0x4c, 0x76, 0x06, 0xad, + 0x8e, 0x8c, 0x29, 0x1a, 0x9b, 0x0f, 0xdd, 0x60, + 0x4b, 0xb4, 0x62, 0x82, 0x9e, 0x4a, 0x63, 0x83, + 0x2e, 0xd2, 0x43, 0x78, 0xc2, 0x32, 0x1f, 0x60, + 0xa9, 0x8a, 0x7f, 0x0f, 0x7c, 0xa6, 0x1d, 0xe6, + 0x92, 0x9e, 0x52, 0xc7, 0x7d, 0xbb, 0x35, 0x3b, + 0xaa, 0x89, 0x73, 0x4c, 0xfb, 0x99, 0x54, 0x97, + 0x99, 0x28, 0x6e, 0x66, 0x5b, 0xf7, 0x9b, 0x7e, + 0x6d, 0x8a, 0x2f, 0xfa, 0xc3, 0x1e, 0x71, 0xb9, + 0xbd, 0x8f, 0xc5, 0x63, 0x25, 0x31, 0x20, 0x02, + 0xff, 0x02, 0xf0, 0xc9, 0x2c, 0xdd, 0x3a, 0x10, + 0x30, 0xab, 0xe5, 0xad, 0x3d, 0x1a, 0x82, 0x77, + 0x46, 0xed, 0x03, 0x38, 0xa4, 0x73, 0x6d, 0x36, + 0x36, 0x33, 0x70, 0xb2, 0x63, 0x20, 0xca, 0x03, + 0xbf, 0x5a, 0xf4, 0x7c, 0x35, 0xf0, 0x63, 0x1a, + 0x12, 0x33, 0x12, 0x58, 0xd9, 0xa2, 0x63, 0x6b, + 0x63, 0x82, 0x41, 0x65, 0x70, 0x37, 0x4b, 0x99, + 0x04, 0x9f, 0xdd, 0x5e, 0x07, 0x01, 0x95, 0x9f, + 0x36, 0xe8, 0xc3, 0x66, 0x2a, 0x21, 0x69, 0x68, + 0x40, 0xe6, 0xbc, 0xbb, 0x85, 0x81, 0x21, 0x13, + 0xe6, 0xa4, 0xcf, 0xd3, 0x67, 0xe3, 0xfd, 0x75, + 0xf0, 0xdf, 0x83, 0xe0, 0xc5, 0x36, 0x09, 0xac, + 0x1b, 0xd4, 0xf7, 0x2a, 0x23, 0x57, 0x1c, 0x5c, + 0x0f, 0xf4, 0xcf, 0xa2, 0xcf, 0xf5, 0xbd, 0x9c, + 0x69, 0x98, 0x78, 0x3a, 0x25, 0xe4, 0xfd, 0x85, + 0x11, 0xcc, 0x7d, 0xef, 0xeb, 0x74, 0x60, 0xb1, + 0xb7, 0xfb, 0x1f, 0x0e, 0x62, 0xff, 0xfe, 0x09, + 0x0a, 0xc3, 0x80, 0x2f, 0x10, 0x49, 0x89, 0x78, + 0xd2, 0x08, 0xfa, 0x89, 0x22, 0x45, 0x91, 0x21, + 0xbc, 0x90, 0x3e, 0xad, 0xb3, 0x0a, 0xb4, 0x0e, + 0x1c, 0xa1, 0x93, 0x92, 0xd8, 0x72, 0x07, 0x54, + 0x60, 0xe7, 0x91, 0xfc, 0xd9, 0x3c, 0xe1, 0x6f, + 0x08, 0xe4, 0x56, 0xf6, 0x0b, 0xb0, 0x3c, 0x39, + 0x8a, 0x2d, 0x48, 0x44, 0x28, 0x13, 0xca, 0xe9, + 0xf7, 0xa3, 0xb6, 0x8a, 0x5f, 0x31, 0xa9, 0x72, + 0xf2, 0xde, 0x96, 0xf2, 0xb1, 0x53, 0xb1, 0x3e, + 0x24, 0x57, 0xfd, 0x18, 0x45, 0x1f, 0xc5, 0x33, + 0x1b, 0xa4, 0xe8, 0x21, 0xfa, 0x0e, 0xb2, 0xb9, + 0xcb, 0xc7, 0x07, 0x41, 0xdd, 0x2f, 0xb6, 0x6a, + 0x23, 0x18, 0xed, 0xc1, 0xef, 0xe2, 0x4b, 0xec, + 0xc9, 0xba, 0xfb, 0x46, 0x43, 0x90, 0xd7, 0xb5, + 0x68, 0x28, 0x31, 0x2b, 0x8d, 0xa8, 0x51, 0x63, + 0xf7, 0x53, 0x99, 0x19, 0x68, 0x85, 0x66, 0x00, + 0x00, 0x00, 0x01, 0x00, 0x05, 0x58, 0x2e, 0x35, + 0x30, 0x39, 0x00, 0x00, 0x02, 0x3a, 0x30, 0x82, + 0x02, 0x36, 0x30, 0x82, 0x01, 0xe0, 0xa0, 0x03, + 0x02, 0x01, 0x02, 0x02, 0x04, 0x48, 0x59, 0xf1, + 0x92, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, + 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, + 0x30, 0x81, 0xa0, 0x31, 0x0b, 0x30, 0x09, 0x06, + 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x4b, 0x52, + 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, + 0x08, 0x13, 0x0a, 0x4b, 0x79, 0x75, 0x6e, 0x67, + 0x67, 0x69, 0x2d, 0x64, 0x6f, 0x31, 0x14, 0x30, + 0x12, 0x06, 0x03, 0x55, 0x04, 0x07, 0x13, 0x0b, + 0x53, 0x65, 0x6f, 0x6e, 0x67, 0x6e, 0x61, 0x6d, + 0x2d, 0x73, 0x69, 0x31, 0x1a, 0x30, 0x18, 0x06, + 0x03, 0x55, 0x04, 0x0a, 0x13, 0x11, 0x54, 0x68, + 0x65, 0x20, 0x4e, 0x65, 0x74, 0x74, 0x79, 0x20, + 0x50, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x31, + 0x18, 0x30, 0x16, 0x06, 0x03, 0x55, 0x04, 0x0b, + 0x13, 0x0f, 0x45, 0x78, 0x61, 0x6d, 0x70, 0x6c, + 0x65, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, + 0x73, 0x31, 0x30, 0x30, 0x2e, 0x06, 0x03, 0x55, + 0x04, 0x03, 0x13, 0x27, 0x73, 0x65, 0x63, 0x75, + 0x72, 0x65, 0x63, 0x68, 0x61, 0x74, 0x2e, 0x65, + 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x2e, 0x6e, + 0x65, 0x74, 0x74, 0x79, 0x2e, 0x67, 0x6c, 0x65, + 0x61, 0x6d, 0x79, 0x6e, 0x6f, 0x64, 0x65, 0x2e, + 0x6e, 0x65, 0x74, 0x30, 0x20, 0x17, 0x0d, 0x30, + 0x38, 0x30, 0x36, 0x31, 0x39, 0x30, 0x35, 0x34, + 0x31, 0x33, 0x38, 0x5a, 0x18, 0x0f, 0x32, 0x31, + 0x38, 0x37, 0x31, 0x31, 0x32, 0x34, 0x30, 0x35, + 0x34, 0x31, 0x33, 0x38, 0x5a, 0x30, 0x81, 0xa0, + 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, + 0x06, 0x13, 0x02, 0x4b, 0x52, 0x31, 0x13, 0x30, + 0x11, 0x06, 0x03, 0x55, 0x04, 0x08, 0x13, 0x0a, + 0x4b, 0x79, 0x75, 0x6e, 0x67, 0x67, 0x69, 0x2d, + 0x64, 0x6f, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, + 0x55, 0x04, 0x07, 0x13, 0x0b, 0x53, 0x65, 0x6f, + 0x6e, 0x67, 0x6e, 0x61, 0x6d, 0x2d, 0x73, 0x69, + 0x31, 0x1a, 0x30, 0x18, 0x06, 0x03, 0x55, 0x04, + 0x0a, 0x13, 0x11, 0x54, 0x68, 0x65, 0x20, 0x4e, + 0x65, 0x74, 0x74, 0x79, 0x20, 0x50, 0x72, 0x6f, + 0x6a, 0x65, 0x63, 0x74, 0x31, 0x18, 0x30, 0x16, + 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 0x0f, 0x45, + 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x20, 0x41, + 0x75, 0x74, 0x68, 0x6f, 0x72, 0x73, 0x31, 0x30, + 0x30, 0x2e, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, + 0x27, 0x73, 0x65, 0x63, 0x75, 0x72, 0x65, 0x63, + 0x68, 0x61, 0x74, 0x2e, 0x65, 0x78, 0x61, 0x6d, + 0x70, 0x6c, 0x65, 0x2e, 0x6e, 0x65, 0x74, 0x74, + 0x79, 0x2e, 0x67, 0x6c, 0x65, 0x61, 0x6d, 0x79, + 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x6e, 0x65, 0x74, + 0x30, 0x5c, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, + 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, + 0x00, 0x03, 0x4b, 0x00, 0x30, 0x48, 0x02, 0x41, + 0x00, 0xc3, 0xe3, 0x5e, 0x41, 0xa7, 0x87, 0x11, + 0x00, 0x42, 0x2a, 0xb0, 0x4b, 0xed, 0xb2, 0xe0, + 0x23, 0xdb, 0xb1, 0x3d, 0x58, 0x97, 0x35, 0x60, + 0x0b, 0x82, 0x59, 0xd3, 0x00, 0xea, 0xd4, 0x61, + 0xb8, 0x79, 0x3f, 0xb6, 0x3c, 0x12, 0x05, 0x93, + 0x2e, 0x9a, 0x59, 0x68, 0x14, 0x77, 0x3a, 0xc8, + 0x50, 0x25, 0x57, 0xa4, 0x49, 0x18, 0x63, 0x41, + 0xf0, 0x2d, 0x28, 0xec, 0x06, 0xfb, 0xb4, 0x9f, + 0xbf, 0x02, 0x03, 0x01, 0x00, 0x01, 0x30, 0x0d, + 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, + 0x01, 0x01, 0x05, 0x05, 0x00, 0x03, 0x41, 0x00, + 0x65, 0x6c, 0x30, 0x01, 0xc2, 0x8e, 0x3e, 0xcb, + 0xb3, 0x77, 0x48, 0xe9, 0x66, 0x61, 0x9a, 0x40, + 0x86, 0xaf, 0xf6, 0x03, 0xeb, 0xba, 0x6a, 0xf2, + 0xfd, 0xe2, 0xaf, 0x36, 0x5e, 0x7b, 0xaa, 0x22, + 0x04, 0xdd, 0x2c, 0x20, 0xc4, 0xfc, 0xdd, 0xd0, + 0x82, 0x20, 0x1c, 0x3d, 0xd7, 0x9e, 0x5e, 0x5c, + 0x92, 0x5a, 0x76, 0x71, 0x28, 0xf5, 0x07, 0x7d, + 0xa2, 0x81, 0xba, 0x77, 0x9f, 0x2a, 0xd9, 0x44, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x05, 0x6d, 0x79, + 0x6b, 0x65, 0x79, 0x00, 0x00, 0x01, 0x1a, 0x9f, + 0x5b, 0x56, 0xa0, 0x00, 0x00, 0x01, 0x99, 0x30, + 0x82, 0x01, 0x95, 0x30, 0x0e, 0x06, 0x0a, 0x2b, + 0x06, 0x01, 0x04, 0x01, 0x2a, 0x02, 0x11, 0x01, + 0x01, 0x05, 0x00, 0x04, 0x82, 0x01, 0x81, 0x29, + 0xa8, 0xb6, 0x08, 0x0c, 0x85, 0x75, 0x3e, 0xdd, + 0xb5, 0xe5, 0x1a, 0x87, 0x68, 0xd1, 0x90, 0x4b, + 0x29, 0x31, 0xee, 0x90, 0xbc, 0x9d, 0x73, 0xa0, + 0x3f, 0xe9, 0x0b, 0xa4, 0xef, 0x30, 0x9b, 0x36, + 0x9a, 0xb2, 0x54, 0x77, 0x81, 0x07, 0x4b, 0xaa, + 0xa5, 0x77, 0x98, 0xe1, 0xeb, 0xb5, 0x7c, 0x4e, + 0x48, 0xd5, 0x08, 0xfc, 0x2c, 0x36, 0xe2, 0x65, + 0x03, 0xac, 0xe5, 0xf3, 0x96, 0xb7, 0xd0, 0xb5, + 0x3b, 0x92, 0xe4, 0x14, 0x05, 0x7a, 0x6a, 0x92, + 0x56, 0xfe, 0x4e, 0xab, 0xd3, 0x0e, 0x32, 0x04, + 0x22, 0x22, 0x74, 0x47, 0x7d, 0xec, 0x21, 0x99, + 0x30, 0x31, 0x64, 0x46, 0x64, 0x9b, 0xc7, 0x13, + 0xbf, 0xbe, 0xd0, 0x31, 0x49, 0xe7, 0x3c, 0xbf, + 0xba, 0xb1, 0x20, 0xf9, 0x42, 0xf4, 0xa9, 0xa9, + 0xe5, 0x13, 0x65, 0x32, 0xbf, 0x7c, 0xcc, 0x91, + 0xd3, 0xfd, 0x24, 0x47, 0x0b, 0xe5, 0x53, 0xad, + 0x50, 0x30, 0x56, 0xd1, 0xfa, 0x9c, 0x37, 0xa8, + 0xc1, 0xce, 0xf6, 0x0b, 0x18, 0xaa, 0x7c, 0xab, + 0xbd, 0x1f, 0xdf, 0xe4, 0x80, 0xb8, 0xa7, 0xe0, + 0xad, 0x7d, 0x50, 0x74, 0xf1, 0x98, 0x78, 0xbc, + 0x58, 0xb9, 0xc2, 0x52, 0xbe, 0xd2, 0x5b, 0x81, + 0x94, 0x83, 0x8f, 0xb9, 0x4c, 0xee, 0x01, 0x2b, + 0x5e, 0xc9, 0x6e, 0x9b, 0xf5, 0x63, 0x69, 0xe4, + 0xd8, 0x0b, 0x47, 0xd8, 0xfd, 0xd8, 0xe0, 0xed, + 0xa8, 0x27, 0x03, 0x74, 0x1e, 0x5d, 0x32, 0xe6, + 0x5c, 0x63, 0xc2, 0xfb, 0x3f, 0xee, 0xb4, 0x13, + 0xc6, 0x0e, 0x6e, 0x74, 0xe0, 0x22, 0xac, 0xce, + 0x79, 0xf9, 0x43, 0x68, 0xc1, 0x03, 0x74, 0x2b, + 0xe1, 0x18, 0xf8, 0x7f, 0x76, 0x9a, 0xea, 0x82, + 0x3f, 0xc2, 0xa6, 0xa7, 0x4c, 0xfe, 0xae, 0x29, + 0x3b, 0xc1, 0x10, 0x7c, 0xd5, 0x77, 0x17, 0x79, + 0x5f, 0xcb, 0xad, 0x1f, 0xd8, 0xa1, 0xfd, 0x90, + 0xe1, 0x6b, 0xb2, 0xef, 0xb9, 0x41, 0x26, 0xa4, + 0x0b, 0x4f, 0xc6, 0x83, 0x05, 0x6f, 0xf0, 0x64, + 0x40, 0xe1, 0x44, 0xc4, 0xf9, 0x40, 0x2b, 0x3b, + 0x40, 0xdb, 0xaf, 0x35, 0xa4, 0x9b, 0x9f, 0xc4, + 0x74, 0x07, 0xe5, 0x18, 0x60, 0xc5, 0xfe, 0x15, + 0x0e, 0x3a, 0x25, 0x2a, 0x11, 0xee, 0x78, 0x2f, + 0xb8, 0xd1, 0x6e, 0x4e, 0x3c, 0x0a, 0xb5, 0xb9, + 0x40, 0x86, 0x27, 0x6d, 0x8f, 0x53, 0xb7, 0x77, + 0x36, 0xec, 0x5d, 0xed, 0x32, 0x40, 0x43, 0x82, + 0xc3, 0x52, 0x58, 0xc4, 0x26, 0x39, 0xf3, 0xb3, + 0xad, 0x58, 0xab, 0xb7, 0xf7, 0x8e, 0x0e, 0xba, + 0x8e, 0x78, 0x9d, 0xbf, 0x58, 0x34, 0xbd, 0x77, + 0x73, 0xa6, 0x50, 0x55, 0x00, 0x60, 0x26, 0xbf, + 0x6d, 0xb4, 0x98, 0x8a, 0x18, 0x83, 0x89, 0xf8, + 0xcd, 0x0d, 0x49, 0x06, 0xae, 0x51, 0x6e, 0xaf, + 0xbd, 0xe2, 0x07, 0x13, 0xd8, 0x64, 0xcc, 0xbf, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x05, 0x58, 0x2e, + 0x35, 0x30, 0x39, 0x00, 0x00, 0x02, 0x34, 0x30, + 0x82, 0x02, 0x30, 0x30, 0x82, 0x01, 0xda, 0xa0, + 0x03, 0x02, 0x01, 0x02, 0x02, 0x04, 0x48, 0x59, + 0xf2, 0x84, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, + 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, + 0x00, 0x30, 0x81, 0x9d, 0x31, 0x0b, 0x30, 0x09, + 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x4b, + 0x52, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, + 0x04, 0x08, 0x13, 0x0a, 0x4b, 0x79, 0x75, 0x6e, + 0x67, 0x67, 0x69, 0x2d, 0x64, 0x6f, 0x31, 0x14, + 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x07, 0x13, + 0x0b, 0x53, 0x65, 0x6f, 0x6e, 0x67, 0x6e, 0x61, + 0x6d, 0x2d, 0x73, 0x69, 0x31, 0x1a, 0x30, 0x18, + 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x11, 0x54, + 0x68, 0x65, 0x20, 0x4e, 0x65, 0x74, 0x74, 0x79, + 0x20, 0x50, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, + 0x31, 0x15, 0x30, 0x13, 0x06, 0x03, 0x55, 0x04, + 0x0b, 0x13, 0x0c, 0x43, 0x6f, 0x6e, 0x74, 0x72, + 0x69, 0x62, 0x75, 0x74, 0x6f, 0x72, 0x73, 0x31, + 0x30, 0x30, 0x2e, 0x06, 0x03, 0x55, 0x04, 0x03, + 0x13, 0x27, 0x73, 0x65, 0x63, 0x75, 0x72, 0x65, + 0x63, 0x68, 0x61, 0x74, 0x2e, 0x65, 0x78, 0x61, + 0x6d, 0x70, 0x6c, 0x65, 0x2e, 0x6e, 0x65, 0x74, + 0x74, 0x79, 0x2e, 0x67, 0x6c, 0x65, 0x61, 0x6d, + 0x79, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x6e, 0x65, + 0x74, 0x30, 0x20, 0x17, 0x0d, 0x30, 0x38, 0x30, + 0x36, 0x31, 0x39, 0x30, 0x35, 0x34, 0x35, 0x34, + 0x30, 0x5a, 0x18, 0x0f, 0x32, 0x31, 0x38, 0x37, + 0x31, 0x31, 0x32, 0x33, 0x30, 0x35, 0x34, 0x35, + 0x34, 0x30, 0x5a, 0x30, 0x81, 0x9d, 0x31, 0x0b, + 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x4b, 0x52, 0x31, 0x13, 0x30, 0x11, 0x06, + 0x03, 0x55, 0x04, 0x08, 0x13, 0x0a, 0x4b, 0x79, + 0x75, 0x6e, 0x67, 0x67, 0x69, 0x2d, 0x64, 0x6f, + 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, + 0x07, 0x13, 0x0b, 0x53, 0x65, 0x6f, 0x6e, 0x67, + 0x6e, 0x61, 0x6d, 0x2d, 0x73, 0x69, 0x31, 0x1a, + 0x30, 0x18, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, + 0x11, 0x54, 0x68, 0x65, 0x20, 0x4e, 0x65, 0x74, + 0x74, 0x79, 0x20, 0x50, 0x72, 0x6f, 0x6a, 0x65, + 0x63, 0x74, 0x31, 0x15, 0x30, 0x13, 0x06, 0x03, + 0x55, 0x04, 0x0b, 0x13, 0x0c, 0x43, 0x6f, 0x6e, + 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x6f, 0x72, + 0x73, 0x31, 0x30, 0x30, 0x2e, 0x06, 0x03, 0x55, + 0x04, 0x03, 0x13, 0x27, 0x73, 0x65, 0x63, 0x75, + 0x72, 0x65, 0x63, 0x68, 0x61, 0x74, 0x2e, 0x65, + 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x2e, 0x6e, + 0x65, 0x74, 0x74, 0x79, 0x2e, 0x67, 0x6c, 0x65, + 0x61, 0x6d, 0x79, 0x6e, 0x6f, 0x64, 0x65, 0x2e, + 0x6e, 0x65, 0x74, 0x30, 0x5c, 0x30, 0x0d, 0x06, + 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, + 0x01, 0x01, 0x05, 0x00, 0x03, 0x4b, 0x00, 0x30, + 0x48, 0x02, 0x41, 0x00, 0x95, 0xb3, 0x47, 0x17, + 0x95, 0x0f, 0x57, 0xcf, 0x66, 0x72, 0x0a, 0x7e, + 0x5b, 0x54, 0xea, 0x8c, 0x6f, 0x79, 0xde, 0x94, + 0xac, 0x0b, 0x5a, 0xd4, 0xd6, 0x1b, 0x58, 0x12, + 0x1a, 0x16, 0x3d, 0xfe, 0xdf, 0xa5, 0x2b, 0x86, + 0xbc, 0x64, 0xd4, 0x80, 0x1e, 0x3f, 0xf9, 0xe2, + 0x04, 0x03, 0x79, 0x9b, 0xc1, 0x5c, 0xf0, 0xf1, + 0xf3, 0xf1, 0xe3, 0xbf, 0x3f, 0xc0, 0x1f, 0xdd, + 0xdb, 0xc0, 0x5b, 0x21, 0x02, 0x03, 0x01, 0x00, + 0x01, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, + 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, + 0x03, 0x41, 0x00, 0x02, 0xd7, 0xdd, 0xbd, 0x0c, + 0x8e, 0x21, 0x20, 0xef, 0x9e, 0x4f, 0x1f, 0xf5, + 0x49, 0xf1, 0xae, 0x58, 0x9b, 0x94, 0x3a, 0x1f, + 0x70, 0x33, 0xf0, 0x9b, 0xbb, 0xe9, 0xc0, 0xf3, + 0x72, 0xcb, 0xde, 0xb6, 0x56, 0x72, 0xcc, 0x1c, + 0xf0, 0xd6, 0x5a, 0x2a, 0xbc, 0xa1, 0x7e, 0x23, + 0x83, 0xe9, 0xe7, 0xcf, 0x9e, 0xa5, 0xf9, 0xcc, + 0xc2, 0x61, 0xf4, 0xdb, 0x40, 0x93, 0x1d, 0x63, + 0x8a, 0x50, 0x4c, 0x11, 0x39, 0xb1, 0x91, 0xc1, + 0xe6, 0x9d, 0xd9, 0x1a, 0x62, 0x1b, 0xb8, 0xd3, + 0xd6, 0x9a, 0x6d, 0xb9, 0x8e, 0x15, 0x51 }; + + public static InputStream asInputStream() { + byte[] data = new byte[DATA.length]; + for (int i = 0; i < data.length; i ++) { + data[i] = (byte) DATA[i]; + } + return new ByteArrayInputStream(data); + } + + public static char[] getCertificatePassword() { + return "secret".toCharArray(); + } + + public static char[] getKeyStorePassword() { + return "secret".toCharArray(); + } + + private SslKeyStore() { + // Unused + } +} diff --git a/src/main/java/com/github/eventsource/client/impl/netty/ssl/SslTrustManagerFactory.java b/src/main/java/com/github/eventsource/client/impl/netty/ssl/SslTrustManagerFactory.java new file mode 100644 index 0000000..7fce441 --- /dev/null +++ b/src/main/java/com/github/eventsource/client/impl/netty/ssl/SslTrustManagerFactory.java @@ -0,0 +1,79 @@ +/* + * Copyright 2012 The Netty Project + * + * The Netty Project licenses this file to you 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 com.github.eventsource.client.impl.netty.ssl; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.net.ssl.ManagerFactoryParameters; +import javax.net.ssl.TrustManager; +import javax.net.ssl.TrustManagerFactorySpi; +import javax.net.ssl.X509TrustManager; +import java.security.InvalidAlgorithmParameterException; +import java.security.KeyStore; +import java.security.KeyStoreException; +import java.security.cert.X509Certificate; + +/** + * Bogus {@link TrustManagerFactorySpi} which accepts any certificate + * even if it is invalid. + */ +public class SslTrustManagerFactory extends TrustManagerFactorySpi { + private static final Logger logger = LoggerFactory.getLogger(SslTrustManagerFactory.class); + + private static final TrustManager DUMMY_TRUST_MANAGER = new X509TrustManager() { + @Override + public X509Certificate[] getAcceptedIssuers() { + return new X509Certificate[0]; + } + + @Override + public void checkClientTrusted(X509Certificate[] chain, String authType) { + // Always trust - it is an example. + // You should do something in the real world. + // You will reach here only if you enabled client certificate auth, + // as described in SslContextFactory. + logger.warn("UNKNOWN CLIENT CERTIFICATE: " + chain[0].getSubjectDN()); + } + + @Override + public void checkServerTrusted(X509Certificate[] chain, String authType) { + // Always trust - it is an example. + // You should do something in the real world. + logger.warn("UNKNOWN SERVER CERTIFICATE: " + chain[0].getSubjectDN()); + } + }; + + public static TrustManager[] getTrustManagers() { + return new TrustManager[] { DUMMY_TRUST_MANAGER }; + } + + @Override + protected TrustManager[] engineGetTrustManagers() { + return getTrustManagers(); + } + + @Override + protected void engineInit(KeyStore keystore) throws KeyStoreException { + // Unused + } + + @Override + protected void engineInit(ManagerFactoryParameters managerFactoryParameters) + throws InvalidAlgorithmParameterException { + // Unused + } +} From df2ce71af5f3d48ee6a7bcd73e1f3f146a53cbe7 Mon Sep 17 00:00:00 2001 From: Dan Noguerol Date: Thu, 15 May 2014 08:53:03 -0600 Subject: [PATCH 02/17] Removed SSL-specific classes. --- .../eventsource/client/EventSource.java | 24 +- .../impl/netty/ssl/SslContextFactory.java | 92 ----- .../client/impl/netty/ssl/SslKeyStore.java | 313 ------------------ .../netty/ssl/SslTrustManagerFactory.java | 79 ----- 4 files changed, 17 insertions(+), 491 deletions(-) delete mode 100644 src/main/java/com/github/eventsource/client/impl/netty/ssl/SslContextFactory.java delete mode 100644 src/main/java/com/github/eventsource/client/impl/netty/ssl/SslKeyStore.java delete mode 100644 src/main/java/com/github/eventsource/client/impl/netty/ssl/SslTrustManagerFactory.java diff --git a/src/main/java/com/github/eventsource/client/EventSource.java b/src/main/java/com/github/eventsource/client/EventSource.java index a54723d..a5beb93 100644 --- a/src/main/java/com/github/eventsource/client/EventSource.java +++ b/src/main/java/com/github/eventsource/client/EventSource.java @@ -2,7 +2,6 @@ import com.github.eventsource.client.impl.AsyncEventSourceHandler; import com.github.eventsource.client.impl.netty.EventSourceChannelHandler; -import com.github.eventsource.client.impl.netty.ssl.SslContextFactory; import org.jboss.netty.bootstrap.ClientBootstrap; import org.jboss.netty.channel.ChannelFuture; import org.jboss.netty.channel.ChannelPipeline; @@ -48,6 +47,10 @@ public class EventSource implements EventSourceHandler { * @see #close() */ public EventSource(Executor executor, long reconnectionTimeMillis, final URI uri, EventSourceHandler eventSourceHandler) { + this(executor, reconnectionTimeMillis, uri, null, eventSourceHandler); + } + + public EventSource(Executor executor, long reconnectionTimeMillis, final URI uri, final SSLEngine sslEngine, EventSourceHandler eventSourceHandler) { this.eventSourceHandler = eventSourceHandler; bootstrap = new ClientBootstrap( @@ -62,10 +65,9 @@ public EventSource(Executor executor, long reconnectionTimeMillis, final URI uri public ChannelPipeline getPipeline() throws Exception { ChannelPipeline pipeline = Channels.pipeline(); - if (uri.getScheme().equalsIgnoreCase("https")) { - SSLEngine engine = SslContextFactory.getClientContext().createSSLEngine(); - engine.setUseClientMode(true); - pipeline.addLast("ssl", new SslHandler(engine)); + if (sslEngine != null) { + sslEngine.setUseClientMode(true); + pipeline.addLast("ssl", new SslHandler(sslEngine)); } pipeline.addLast("line", new DelimiterBasedFrameDecoder(Integer.MAX_VALUE, Delimiters.lineDelimiter())); @@ -79,11 +81,19 @@ public ChannelPipeline getPipeline() throws Exception { } public EventSource(String uri, EventSourceHandler eventSourceHandler) { - this(URI.create(uri), eventSourceHandler); + this(uri, null, eventSourceHandler); + } + + public EventSource(String uri, SSLEngine sslEngine, EventSourceHandler eventSourceHandler) { + this(URI.create(uri), sslEngine, eventSourceHandler); } public EventSource(URI uri, EventSourceHandler eventSourceHandler) { - this(Executors.newSingleThreadExecutor(), DEFAULT_RECONNECTION_TIME_MILLIS, uri, eventSourceHandler); + this(uri, null, eventSourceHandler); + } + + public EventSource(URI uri, SSLEngine sslEngine, EventSourceHandler eventSourceHandler) { + this(Executors.newSingleThreadExecutor(), DEFAULT_RECONNECTION_TIME_MILLIS, uri, sslEngine, eventSourceHandler); } public void setCustomRequestHeader(String name, String value) { diff --git a/src/main/java/com/github/eventsource/client/impl/netty/ssl/SslContextFactory.java b/src/main/java/com/github/eventsource/client/impl/netty/ssl/SslContextFactory.java deleted file mode 100644 index 48ec8dc..0000000 --- a/src/main/java/com/github/eventsource/client/impl/netty/ssl/SslContextFactory.java +++ /dev/null @@ -1,92 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you 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 com.github.eventsource.client.impl.netty.ssl; - -import javax.net.ssl.KeyManagerFactory; -import javax.net.ssl.SSLContext; -import java.security.KeyStore; -import java.security.Security; - -/** - * Creates a bogus {@link SSLContext}. A client-side context created by this - * factory accepts any certificate even if it is invalid. A server-side context - * created by this factory sends a bogus certificate defined in {@link SecureChatKeyStore}. - *

- * You will have to create your context differently in a real world application. - * - *

Client Certificate Authentication

- * - * To enable client certificate authentication: - *
    - *
  • Enable client authentication on the server side by calling - * {@link SSLEngine#setNeedClientAuth(boolean)} before creating - * {@link SslHandler}.
  • - *
  • When initializing an {@link SSLContext} on the client side, - * specify the {@link KeyManager} that contains the client certificate as - * the first argument of {@link SSLContext#init(KeyManager[], TrustManager[], SecureRandom)}.
  • - *
  • When initializing an {@link SSLContext} on the server side, - * specify the proper {@link TrustManager} as the second argument of - * {@link SSLContext#init(KeyManager[], TrustManager[], SecureRandom)} - * to validate the client certificate.
  • - *
- */ -public class SslContextFactory { - private static final String PROTOCOL = "TLS"; - private static final SSLContext SERVER_CONTEXT; - private static final SSLContext CLIENT_CONTEXT; - - static { - String algorithm = Security.getProperty("ssl.KeyManagerFactory.algorithm"); - if (algorithm == null) { - algorithm = "SunX509"; - } - - SSLContext serverContext = null; - SSLContext clientContext = null; - try { - KeyStore ks = KeyStore.getInstance("JKS"); - ks.load(SslKeyStore.asInputStream(), SslKeyStore.getKeyStorePassword()); - - // Set up key manager factory to use our key store - KeyManagerFactory kmf = KeyManagerFactory.getInstance(algorithm); - kmf.init(ks, SslKeyStore.getCertificatePassword()); - - // Initialize the SSLContext to work with our key managers. - serverContext = SSLContext.getInstance(PROTOCOL); - serverContext.init(kmf.getKeyManagers(), null, null); - } catch (Exception e) { - throw new Error("Failed to initialize the server-side SSLContext", e); - } - - try { - clientContext = SSLContext.getInstance(PROTOCOL); - clientContext.init(null, SslTrustManagerFactory.getTrustManagers(), null); - } catch (Exception e) { - throw new Error("Failed to initialize the client-side SSLContext", e); - } - - SERVER_CONTEXT = serverContext; - CLIENT_CONTEXT = clientContext; - } - - public static SSLContext getServerContext() { - return SERVER_CONTEXT; - } - - public static SSLContext getClientContext() { - return CLIENT_CONTEXT; - } -} diff --git a/src/main/java/com/github/eventsource/client/impl/netty/ssl/SslKeyStore.java b/src/main/java/com/github/eventsource/client/impl/netty/ssl/SslKeyStore.java deleted file mode 100644 index 63a0347..0000000 --- a/src/main/java/com/github/eventsource/client/impl/netty/ssl/SslKeyStore.java +++ /dev/null @@ -1,313 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you 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 com.github.eventsource.client.impl.netty.ssl; - -import java.io.ByteArrayInputStream; -import java.io.InputStream; - -/** - * A bogus key store which provides all the required information to - * create an example SSL connection. - * - * To generate a bogus key store: - *
- * keytool  -genkey -alias securechat -keysize 2048 -validity 36500
- *          -keyalg RSA -dname "CN=securechat"
- *          -keypass secret -storepass secret
- *          -keystore cert.jks
- * 
- */ -public class SslKeyStore { - private static final short[] DATA = { - 0xfe, 0xed, 0xfe, 0xed, 0x00, 0x00, 0x00, 0x02, - 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, - 0x00, 0x07, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, - 0x65, 0x00, 0x00, 0x01, 0x1a, 0x9f, 0x57, 0xa5, - 0x27, 0x00, 0x00, 0x01, 0x9a, 0x30, 0x82, 0x01, - 0x96, 0x30, 0x0e, 0x06, 0x0a, 0x2b, 0x06, 0x01, - 0x04, 0x01, 0x2a, 0x02, 0x11, 0x01, 0x01, 0x05, - 0x00, 0x04, 0x82, 0x01, 0x82, 0x48, 0x6d, 0xcf, - 0x16, 0xb5, 0x50, 0x95, 0x36, 0xbf, 0x47, 0x27, - 0x50, 0x58, 0x0d, 0xa2, 0x52, 0x7e, 0x25, 0xab, - 0x14, 0x1a, 0x26, 0x5e, 0x2d, 0x8a, 0x23, 0x90, - 0x60, 0x7f, 0x12, 0x20, 0x56, 0xd1, 0x43, 0xa2, - 0x6b, 0x47, 0x5d, 0xed, 0x9d, 0xd4, 0xe5, 0x83, - 0x28, 0x89, 0xc2, 0x16, 0x4c, 0x76, 0x06, 0xad, - 0x8e, 0x8c, 0x29, 0x1a, 0x9b, 0x0f, 0xdd, 0x60, - 0x4b, 0xb4, 0x62, 0x82, 0x9e, 0x4a, 0x63, 0x83, - 0x2e, 0xd2, 0x43, 0x78, 0xc2, 0x32, 0x1f, 0x60, - 0xa9, 0x8a, 0x7f, 0x0f, 0x7c, 0xa6, 0x1d, 0xe6, - 0x92, 0x9e, 0x52, 0xc7, 0x7d, 0xbb, 0x35, 0x3b, - 0xaa, 0x89, 0x73, 0x4c, 0xfb, 0x99, 0x54, 0x97, - 0x99, 0x28, 0x6e, 0x66, 0x5b, 0xf7, 0x9b, 0x7e, - 0x6d, 0x8a, 0x2f, 0xfa, 0xc3, 0x1e, 0x71, 0xb9, - 0xbd, 0x8f, 0xc5, 0x63, 0x25, 0x31, 0x20, 0x02, - 0xff, 0x02, 0xf0, 0xc9, 0x2c, 0xdd, 0x3a, 0x10, - 0x30, 0xab, 0xe5, 0xad, 0x3d, 0x1a, 0x82, 0x77, - 0x46, 0xed, 0x03, 0x38, 0xa4, 0x73, 0x6d, 0x36, - 0x36, 0x33, 0x70, 0xb2, 0x63, 0x20, 0xca, 0x03, - 0xbf, 0x5a, 0xf4, 0x7c, 0x35, 0xf0, 0x63, 0x1a, - 0x12, 0x33, 0x12, 0x58, 0xd9, 0xa2, 0x63, 0x6b, - 0x63, 0x82, 0x41, 0x65, 0x70, 0x37, 0x4b, 0x99, - 0x04, 0x9f, 0xdd, 0x5e, 0x07, 0x01, 0x95, 0x9f, - 0x36, 0xe8, 0xc3, 0x66, 0x2a, 0x21, 0x69, 0x68, - 0x40, 0xe6, 0xbc, 0xbb, 0x85, 0x81, 0x21, 0x13, - 0xe6, 0xa4, 0xcf, 0xd3, 0x67, 0xe3, 0xfd, 0x75, - 0xf0, 0xdf, 0x83, 0xe0, 0xc5, 0x36, 0x09, 0xac, - 0x1b, 0xd4, 0xf7, 0x2a, 0x23, 0x57, 0x1c, 0x5c, - 0x0f, 0xf4, 0xcf, 0xa2, 0xcf, 0xf5, 0xbd, 0x9c, - 0x69, 0x98, 0x78, 0x3a, 0x25, 0xe4, 0xfd, 0x85, - 0x11, 0xcc, 0x7d, 0xef, 0xeb, 0x74, 0x60, 0xb1, - 0xb7, 0xfb, 0x1f, 0x0e, 0x62, 0xff, 0xfe, 0x09, - 0x0a, 0xc3, 0x80, 0x2f, 0x10, 0x49, 0x89, 0x78, - 0xd2, 0x08, 0xfa, 0x89, 0x22, 0x45, 0x91, 0x21, - 0xbc, 0x90, 0x3e, 0xad, 0xb3, 0x0a, 0xb4, 0x0e, - 0x1c, 0xa1, 0x93, 0x92, 0xd8, 0x72, 0x07, 0x54, - 0x60, 0xe7, 0x91, 0xfc, 0xd9, 0x3c, 0xe1, 0x6f, - 0x08, 0xe4, 0x56, 0xf6, 0x0b, 0xb0, 0x3c, 0x39, - 0x8a, 0x2d, 0x48, 0x44, 0x28, 0x13, 0xca, 0xe9, - 0xf7, 0xa3, 0xb6, 0x8a, 0x5f, 0x31, 0xa9, 0x72, - 0xf2, 0xde, 0x96, 0xf2, 0xb1, 0x53, 0xb1, 0x3e, - 0x24, 0x57, 0xfd, 0x18, 0x45, 0x1f, 0xc5, 0x33, - 0x1b, 0xa4, 0xe8, 0x21, 0xfa, 0x0e, 0xb2, 0xb9, - 0xcb, 0xc7, 0x07, 0x41, 0xdd, 0x2f, 0xb6, 0x6a, - 0x23, 0x18, 0xed, 0xc1, 0xef, 0xe2, 0x4b, 0xec, - 0xc9, 0xba, 0xfb, 0x46, 0x43, 0x90, 0xd7, 0xb5, - 0x68, 0x28, 0x31, 0x2b, 0x8d, 0xa8, 0x51, 0x63, - 0xf7, 0x53, 0x99, 0x19, 0x68, 0x85, 0x66, 0x00, - 0x00, 0x00, 0x01, 0x00, 0x05, 0x58, 0x2e, 0x35, - 0x30, 0x39, 0x00, 0x00, 0x02, 0x3a, 0x30, 0x82, - 0x02, 0x36, 0x30, 0x82, 0x01, 0xe0, 0xa0, 0x03, - 0x02, 0x01, 0x02, 0x02, 0x04, 0x48, 0x59, 0xf1, - 0x92, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, - 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, - 0x30, 0x81, 0xa0, 0x31, 0x0b, 0x30, 0x09, 0x06, - 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x4b, 0x52, - 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, - 0x08, 0x13, 0x0a, 0x4b, 0x79, 0x75, 0x6e, 0x67, - 0x67, 0x69, 0x2d, 0x64, 0x6f, 0x31, 0x14, 0x30, - 0x12, 0x06, 0x03, 0x55, 0x04, 0x07, 0x13, 0x0b, - 0x53, 0x65, 0x6f, 0x6e, 0x67, 0x6e, 0x61, 0x6d, - 0x2d, 0x73, 0x69, 0x31, 0x1a, 0x30, 0x18, 0x06, - 0x03, 0x55, 0x04, 0x0a, 0x13, 0x11, 0x54, 0x68, - 0x65, 0x20, 0x4e, 0x65, 0x74, 0x74, 0x79, 0x20, - 0x50, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x31, - 0x18, 0x30, 0x16, 0x06, 0x03, 0x55, 0x04, 0x0b, - 0x13, 0x0f, 0x45, 0x78, 0x61, 0x6d, 0x70, 0x6c, - 0x65, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, - 0x73, 0x31, 0x30, 0x30, 0x2e, 0x06, 0x03, 0x55, - 0x04, 0x03, 0x13, 0x27, 0x73, 0x65, 0x63, 0x75, - 0x72, 0x65, 0x63, 0x68, 0x61, 0x74, 0x2e, 0x65, - 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x2e, 0x6e, - 0x65, 0x74, 0x74, 0x79, 0x2e, 0x67, 0x6c, 0x65, - 0x61, 0x6d, 0x79, 0x6e, 0x6f, 0x64, 0x65, 0x2e, - 0x6e, 0x65, 0x74, 0x30, 0x20, 0x17, 0x0d, 0x30, - 0x38, 0x30, 0x36, 0x31, 0x39, 0x30, 0x35, 0x34, - 0x31, 0x33, 0x38, 0x5a, 0x18, 0x0f, 0x32, 0x31, - 0x38, 0x37, 0x31, 0x31, 0x32, 0x34, 0x30, 0x35, - 0x34, 0x31, 0x33, 0x38, 0x5a, 0x30, 0x81, 0xa0, - 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, - 0x06, 0x13, 0x02, 0x4b, 0x52, 0x31, 0x13, 0x30, - 0x11, 0x06, 0x03, 0x55, 0x04, 0x08, 0x13, 0x0a, - 0x4b, 0x79, 0x75, 0x6e, 0x67, 0x67, 0x69, 0x2d, - 0x64, 0x6f, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, - 0x55, 0x04, 0x07, 0x13, 0x0b, 0x53, 0x65, 0x6f, - 0x6e, 0x67, 0x6e, 0x61, 0x6d, 0x2d, 0x73, 0x69, - 0x31, 0x1a, 0x30, 0x18, 0x06, 0x03, 0x55, 0x04, - 0x0a, 0x13, 0x11, 0x54, 0x68, 0x65, 0x20, 0x4e, - 0x65, 0x74, 0x74, 0x79, 0x20, 0x50, 0x72, 0x6f, - 0x6a, 0x65, 0x63, 0x74, 0x31, 0x18, 0x30, 0x16, - 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 0x0f, 0x45, - 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x20, 0x41, - 0x75, 0x74, 0x68, 0x6f, 0x72, 0x73, 0x31, 0x30, - 0x30, 0x2e, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, - 0x27, 0x73, 0x65, 0x63, 0x75, 0x72, 0x65, 0x63, - 0x68, 0x61, 0x74, 0x2e, 0x65, 0x78, 0x61, 0x6d, - 0x70, 0x6c, 0x65, 0x2e, 0x6e, 0x65, 0x74, 0x74, - 0x79, 0x2e, 0x67, 0x6c, 0x65, 0x61, 0x6d, 0x79, - 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x6e, 0x65, 0x74, - 0x30, 0x5c, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, - 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, - 0x00, 0x03, 0x4b, 0x00, 0x30, 0x48, 0x02, 0x41, - 0x00, 0xc3, 0xe3, 0x5e, 0x41, 0xa7, 0x87, 0x11, - 0x00, 0x42, 0x2a, 0xb0, 0x4b, 0xed, 0xb2, 0xe0, - 0x23, 0xdb, 0xb1, 0x3d, 0x58, 0x97, 0x35, 0x60, - 0x0b, 0x82, 0x59, 0xd3, 0x00, 0xea, 0xd4, 0x61, - 0xb8, 0x79, 0x3f, 0xb6, 0x3c, 0x12, 0x05, 0x93, - 0x2e, 0x9a, 0x59, 0x68, 0x14, 0x77, 0x3a, 0xc8, - 0x50, 0x25, 0x57, 0xa4, 0x49, 0x18, 0x63, 0x41, - 0xf0, 0x2d, 0x28, 0xec, 0x06, 0xfb, 0xb4, 0x9f, - 0xbf, 0x02, 0x03, 0x01, 0x00, 0x01, 0x30, 0x0d, - 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, - 0x01, 0x01, 0x05, 0x05, 0x00, 0x03, 0x41, 0x00, - 0x65, 0x6c, 0x30, 0x01, 0xc2, 0x8e, 0x3e, 0xcb, - 0xb3, 0x77, 0x48, 0xe9, 0x66, 0x61, 0x9a, 0x40, - 0x86, 0xaf, 0xf6, 0x03, 0xeb, 0xba, 0x6a, 0xf2, - 0xfd, 0xe2, 0xaf, 0x36, 0x5e, 0x7b, 0xaa, 0x22, - 0x04, 0xdd, 0x2c, 0x20, 0xc4, 0xfc, 0xdd, 0xd0, - 0x82, 0x20, 0x1c, 0x3d, 0xd7, 0x9e, 0x5e, 0x5c, - 0x92, 0x5a, 0x76, 0x71, 0x28, 0xf5, 0x07, 0x7d, - 0xa2, 0x81, 0xba, 0x77, 0x9f, 0x2a, 0xd9, 0x44, - 0x00, 0x00, 0x00, 0x01, 0x00, 0x05, 0x6d, 0x79, - 0x6b, 0x65, 0x79, 0x00, 0x00, 0x01, 0x1a, 0x9f, - 0x5b, 0x56, 0xa0, 0x00, 0x00, 0x01, 0x99, 0x30, - 0x82, 0x01, 0x95, 0x30, 0x0e, 0x06, 0x0a, 0x2b, - 0x06, 0x01, 0x04, 0x01, 0x2a, 0x02, 0x11, 0x01, - 0x01, 0x05, 0x00, 0x04, 0x82, 0x01, 0x81, 0x29, - 0xa8, 0xb6, 0x08, 0x0c, 0x85, 0x75, 0x3e, 0xdd, - 0xb5, 0xe5, 0x1a, 0x87, 0x68, 0xd1, 0x90, 0x4b, - 0x29, 0x31, 0xee, 0x90, 0xbc, 0x9d, 0x73, 0xa0, - 0x3f, 0xe9, 0x0b, 0xa4, 0xef, 0x30, 0x9b, 0x36, - 0x9a, 0xb2, 0x54, 0x77, 0x81, 0x07, 0x4b, 0xaa, - 0xa5, 0x77, 0x98, 0xe1, 0xeb, 0xb5, 0x7c, 0x4e, - 0x48, 0xd5, 0x08, 0xfc, 0x2c, 0x36, 0xe2, 0x65, - 0x03, 0xac, 0xe5, 0xf3, 0x96, 0xb7, 0xd0, 0xb5, - 0x3b, 0x92, 0xe4, 0x14, 0x05, 0x7a, 0x6a, 0x92, - 0x56, 0xfe, 0x4e, 0xab, 0xd3, 0x0e, 0x32, 0x04, - 0x22, 0x22, 0x74, 0x47, 0x7d, 0xec, 0x21, 0x99, - 0x30, 0x31, 0x64, 0x46, 0x64, 0x9b, 0xc7, 0x13, - 0xbf, 0xbe, 0xd0, 0x31, 0x49, 0xe7, 0x3c, 0xbf, - 0xba, 0xb1, 0x20, 0xf9, 0x42, 0xf4, 0xa9, 0xa9, - 0xe5, 0x13, 0x65, 0x32, 0xbf, 0x7c, 0xcc, 0x91, - 0xd3, 0xfd, 0x24, 0x47, 0x0b, 0xe5, 0x53, 0xad, - 0x50, 0x30, 0x56, 0xd1, 0xfa, 0x9c, 0x37, 0xa8, - 0xc1, 0xce, 0xf6, 0x0b, 0x18, 0xaa, 0x7c, 0xab, - 0xbd, 0x1f, 0xdf, 0xe4, 0x80, 0xb8, 0xa7, 0xe0, - 0xad, 0x7d, 0x50, 0x74, 0xf1, 0x98, 0x78, 0xbc, - 0x58, 0xb9, 0xc2, 0x52, 0xbe, 0xd2, 0x5b, 0x81, - 0x94, 0x83, 0x8f, 0xb9, 0x4c, 0xee, 0x01, 0x2b, - 0x5e, 0xc9, 0x6e, 0x9b, 0xf5, 0x63, 0x69, 0xe4, - 0xd8, 0x0b, 0x47, 0xd8, 0xfd, 0xd8, 0xe0, 0xed, - 0xa8, 0x27, 0x03, 0x74, 0x1e, 0x5d, 0x32, 0xe6, - 0x5c, 0x63, 0xc2, 0xfb, 0x3f, 0xee, 0xb4, 0x13, - 0xc6, 0x0e, 0x6e, 0x74, 0xe0, 0x22, 0xac, 0xce, - 0x79, 0xf9, 0x43, 0x68, 0xc1, 0x03, 0x74, 0x2b, - 0xe1, 0x18, 0xf8, 0x7f, 0x76, 0x9a, 0xea, 0x82, - 0x3f, 0xc2, 0xa6, 0xa7, 0x4c, 0xfe, 0xae, 0x29, - 0x3b, 0xc1, 0x10, 0x7c, 0xd5, 0x77, 0x17, 0x79, - 0x5f, 0xcb, 0xad, 0x1f, 0xd8, 0xa1, 0xfd, 0x90, - 0xe1, 0x6b, 0xb2, 0xef, 0xb9, 0x41, 0x26, 0xa4, - 0x0b, 0x4f, 0xc6, 0x83, 0x05, 0x6f, 0xf0, 0x64, - 0x40, 0xe1, 0x44, 0xc4, 0xf9, 0x40, 0x2b, 0x3b, - 0x40, 0xdb, 0xaf, 0x35, 0xa4, 0x9b, 0x9f, 0xc4, - 0x74, 0x07, 0xe5, 0x18, 0x60, 0xc5, 0xfe, 0x15, - 0x0e, 0x3a, 0x25, 0x2a, 0x11, 0xee, 0x78, 0x2f, - 0xb8, 0xd1, 0x6e, 0x4e, 0x3c, 0x0a, 0xb5, 0xb9, - 0x40, 0x86, 0x27, 0x6d, 0x8f, 0x53, 0xb7, 0x77, - 0x36, 0xec, 0x5d, 0xed, 0x32, 0x40, 0x43, 0x82, - 0xc3, 0x52, 0x58, 0xc4, 0x26, 0x39, 0xf3, 0xb3, - 0xad, 0x58, 0xab, 0xb7, 0xf7, 0x8e, 0x0e, 0xba, - 0x8e, 0x78, 0x9d, 0xbf, 0x58, 0x34, 0xbd, 0x77, - 0x73, 0xa6, 0x50, 0x55, 0x00, 0x60, 0x26, 0xbf, - 0x6d, 0xb4, 0x98, 0x8a, 0x18, 0x83, 0x89, 0xf8, - 0xcd, 0x0d, 0x49, 0x06, 0xae, 0x51, 0x6e, 0xaf, - 0xbd, 0xe2, 0x07, 0x13, 0xd8, 0x64, 0xcc, 0xbf, - 0x00, 0x00, 0x00, 0x01, 0x00, 0x05, 0x58, 0x2e, - 0x35, 0x30, 0x39, 0x00, 0x00, 0x02, 0x34, 0x30, - 0x82, 0x02, 0x30, 0x30, 0x82, 0x01, 0xda, 0xa0, - 0x03, 0x02, 0x01, 0x02, 0x02, 0x04, 0x48, 0x59, - 0xf2, 0x84, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, - 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, - 0x00, 0x30, 0x81, 0x9d, 0x31, 0x0b, 0x30, 0x09, - 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x4b, - 0x52, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, - 0x04, 0x08, 0x13, 0x0a, 0x4b, 0x79, 0x75, 0x6e, - 0x67, 0x67, 0x69, 0x2d, 0x64, 0x6f, 0x31, 0x14, - 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x07, 0x13, - 0x0b, 0x53, 0x65, 0x6f, 0x6e, 0x67, 0x6e, 0x61, - 0x6d, 0x2d, 0x73, 0x69, 0x31, 0x1a, 0x30, 0x18, - 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x11, 0x54, - 0x68, 0x65, 0x20, 0x4e, 0x65, 0x74, 0x74, 0x79, - 0x20, 0x50, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, - 0x31, 0x15, 0x30, 0x13, 0x06, 0x03, 0x55, 0x04, - 0x0b, 0x13, 0x0c, 0x43, 0x6f, 0x6e, 0x74, 0x72, - 0x69, 0x62, 0x75, 0x74, 0x6f, 0x72, 0x73, 0x31, - 0x30, 0x30, 0x2e, 0x06, 0x03, 0x55, 0x04, 0x03, - 0x13, 0x27, 0x73, 0x65, 0x63, 0x75, 0x72, 0x65, - 0x63, 0x68, 0x61, 0x74, 0x2e, 0x65, 0x78, 0x61, - 0x6d, 0x70, 0x6c, 0x65, 0x2e, 0x6e, 0x65, 0x74, - 0x74, 0x79, 0x2e, 0x67, 0x6c, 0x65, 0x61, 0x6d, - 0x79, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x6e, 0x65, - 0x74, 0x30, 0x20, 0x17, 0x0d, 0x30, 0x38, 0x30, - 0x36, 0x31, 0x39, 0x30, 0x35, 0x34, 0x35, 0x34, - 0x30, 0x5a, 0x18, 0x0f, 0x32, 0x31, 0x38, 0x37, - 0x31, 0x31, 0x32, 0x33, 0x30, 0x35, 0x34, 0x35, - 0x34, 0x30, 0x5a, 0x30, 0x81, 0x9d, 0x31, 0x0b, - 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, - 0x02, 0x4b, 0x52, 0x31, 0x13, 0x30, 0x11, 0x06, - 0x03, 0x55, 0x04, 0x08, 0x13, 0x0a, 0x4b, 0x79, - 0x75, 0x6e, 0x67, 0x67, 0x69, 0x2d, 0x64, 0x6f, - 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, - 0x07, 0x13, 0x0b, 0x53, 0x65, 0x6f, 0x6e, 0x67, - 0x6e, 0x61, 0x6d, 0x2d, 0x73, 0x69, 0x31, 0x1a, - 0x30, 0x18, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, - 0x11, 0x54, 0x68, 0x65, 0x20, 0x4e, 0x65, 0x74, - 0x74, 0x79, 0x20, 0x50, 0x72, 0x6f, 0x6a, 0x65, - 0x63, 0x74, 0x31, 0x15, 0x30, 0x13, 0x06, 0x03, - 0x55, 0x04, 0x0b, 0x13, 0x0c, 0x43, 0x6f, 0x6e, - 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x6f, 0x72, - 0x73, 0x31, 0x30, 0x30, 0x2e, 0x06, 0x03, 0x55, - 0x04, 0x03, 0x13, 0x27, 0x73, 0x65, 0x63, 0x75, - 0x72, 0x65, 0x63, 0x68, 0x61, 0x74, 0x2e, 0x65, - 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x2e, 0x6e, - 0x65, 0x74, 0x74, 0x79, 0x2e, 0x67, 0x6c, 0x65, - 0x61, 0x6d, 0x79, 0x6e, 0x6f, 0x64, 0x65, 0x2e, - 0x6e, 0x65, 0x74, 0x30, 0x5c, 0x30, 0x0d, 0x06, - 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, - 0x01, 0x01, 0x05, 0x00, 0x03, 0x4b, 0x00, 0x30, - 0x48, 0x02, 0x41, 0x00, 0x95, 0xb3, 0x47, 0x17, - 0x95, 0x0f, 0x57, 0xcf, 0x66, 0x72, 0x0a, 0x7e, - 0x5b, 0x54, 0xea, 0x8c, 0x6f, 0x79, 0xde, 0x94, - 0xac, 0x0b, 0x5a, 0xd4, 0xd6, 0x1b, 0x58, 0x12, - 0x1a, 0x16, 0x3d, 0xfe, 0xdf, 0xa5, 0x2b, 0x86, - 0xbc, 0x64, 0xd4, 0x80, 0x1e, 0x3f, 0xf9, 0xe2, - 0x04, 0x03, 0x79, 0x9b, 0xc1, 0x5c, 0xf0, 0xf1, - 0xf3, 0xf1, 0xe3, 0xbf, 0x3f, 0xc0, 0x1f, 0xdd, - 0xdb, 0xc0, 0x5b, 0x21, 0x02, 0x03, 0x01, 0x00, - 0x01, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, - 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, - 0x03, 0x41, 0x00, 0x02, 0xd7, 0xdd, 0xbd, 0x0c, - 0x8e, 0x21, 0x20, 0xef, 0x9e, 0x4f, 0x1f, 0xf5, - 0x49, 0xf1, 0xae, 0x58, 0x9b, 0x94, 0x3a, 0x1f, - 0x70, 0x33, 0xf0, 0x9b, 0xbb, 0xe9, 0xc0, 0xf3, - 0x72, 0xcb, 0xde, 0xb6, 0x56, 0x72, 0xcc, 0x1c, - 0xf0, 0xd6, 0x5a, 0x2a, 0xbc, 0xa1, 0x7e, 0x23, - 0x83, 0xe9, 0xe7, 0xcf, 0x9e, 0xa5, 0xf9, 0xcc, - 0xc2, 0x61, 0xf4, 0xdb, 0x40, 0x93, 0x1d, 0x63, - 0x8a, 0x50, 0x4c, 0x11, 0x39, 0xb1, 0x91, 0xc1, - 0xe6, 0x9d, 0xd9, 0x1a, 0x62, 0x1b, 0xb8, 0xd3, - 0xd6, 0x9a, 0x6d, 0xb9, 0x8e, 0x15, 0x51 }; - - public static InputStream asInputStream() { - byte[] data = new byte[DATA.length]; - for (int i = 0; i < data.length; i ++) { - data[i] = (byte) DATA[i]; - } - return new ByteArrayInputStream(data); - } - - public static char[] getCertificatePassword() { - return "secret".toCharArray(); - } - - public static char[] getKeyStorePassword() { - return "secret".toCharArray(); - } - - private SslKeyStore() { - // Unused - } -} diff --git a/src/main/java/com/github/eventsource/client/impl/netty/ssl/SslTrustManagerFactory.java b/src/main/java/com/github/eventsource/client/impl/netty/ssl/SslTrustManagerFactory.java deleted file mode 100644 index 7fce441..0000000 --- a/src/main/java/com/github/eventsource/client/impl/netty/ssl/SslTrustManagerFactory.java +++ /dev/null @@ -1,79 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you 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 com.github.eventsource.client.impl.netty.ssl; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import javax.net.ssl.ManagerFactoryParameters; -import javax.net.ssl.TrustManager; -import javax.net.ssl.TrustManagerFactorySpi; -import javax.net.ssl.X509TrustManager; -import java.security.InvalidAlgorithmParameterException; -import java.security.KeyStore; -import java.security.KeyStoreException; -import java.security.cert.X509Certificate; - -/** - * Bogus {@link TrustManagerFactorySpi} which accepts any certificate - * even if it is invalid. - */ -public class SslTrustManagerFactory extends TrustManagerFactorySpi { - private static final Logger logger = LoggerFactory.getLogger(SslTrustManagerFactory.class); - - private static final TrustManager DUMMY_TRUST_MANAGER = new X509TrustManager() { - @Override - public X509Certificate[] getAcceptedIssuers() { - return new X509Certificate[0]; - } - - @Override - public void checkClientTrusted(X509Certificate[] chain, String authType) { - // Always trust - it is an example. - // You should do something in the real world. - // You will reach here only if you enabled client certificate auth, - // as described in SslContextFactory. - logger.warn("UNKNOWN CLIENT CERTIFICATE: " + chain[0].getSubjectDN()); - } - - @Override - public void checkServerTrusted(X509Certificate[] chain, String authType) { - // Always trust - it is an example. - // You should do something in the real world. - logger.warn("UNKNOWN SERVER CERTIFICATE: " + chain[0].getSubjectDN()); - } - }; - - public static TrustManager[] getTrustManagers() { - return new TrustManager[] { DUMMY_TRUST_MANAGER }; - } - - @Override - protected TrustManager[] engineGetTrustManagers() { - return getTrustManagers(); - } - - @Override - protected void engineInit(KeyStore keystore) throws KeyStoreException { - // Unused - } - - @Override - protected void engineInit(ManagerFactoryParameters managerFactoryParameters) - throws InvalidAlgorithmParameterException { - // Unused - } -} From d18efa143e38506fd45ac8ba49103a28a1ab00eb Mon Sep 17 00:00:00 2001 From: Dan Noguerol Date: Thu, 15 May 2014 09:02:38 -0600 Subject: [PATCH 03/17] Added some comments. --- .../github/eventsource/client/EventSource.java | 16 +++++++++++++++- .../impl/netty/EventSourceChannelHandler.java | 7 +++++++ 2 files changed, 22 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/github/eventsource/client/EventSource.java b/src/main/java/com/github/eventsource/client/EventSource.java index a5beb93..31368d2 100644 --- a/src/main/java/com/github/eventsource/client/EventSource.java +++ b/src/main/java/com/github/eventsource/client/EventSource.java @@ -59,7 +59,10 @@ public EventSource(Executor executor, long reconnectionTimeMillis, final URI uri Executors.newSingleThreadExecutor())); bootstrap.setOption("remoteAddress", new InetSocketAddress(uri.getHost(), uri.getPort())); - clientHandler = new EventSourceChannelHandler(new AsyncEventSourceHandler(executor, eventSourceHandler), reconnectionTimeMillis, bootstrap, uri); + // add this class as the event source handler so the connect() call can be intercepted + AsyncEventSourceHandler asyncHandler = new AsyncEventSourceHandler(executor, this); + + clientHandler = new EventSourceChannelHandler(asyncHandler, reconnectionTimeMillis, bootstrap, uri); bootstrap.setPipelineFactory(new ChannelPipelineFactory() { public ChannelPipeline getPipeline() throws Exception { @@ -96,6 +99,12 @@ public EventSource(URI uri, SSLEngine sslEngine, EventSourceHandler eventSourceH this(Executors.newSingleThreadExecutor(), DEFAULT_RECONNECTION_TIME_MILLIS, uri, sslEngine, eventSourceHandler); } + /** + * Sets a custom HTTP header that will be used when the request is made to establish the SSE channel. + * + * @param name the HTTP header name + * @param value the header value + */ public void setCustomRequestHeader(String name, String value) { clientHandler.setCustomRequestHeader(name, value); } @@ -133,17 +142,22 @@ public EventSource join() throws InterruptedException { @Override public void onConnect() throws Exception { + // flag the connection as open readyState = OPEN; + + // pass event to the proper handler eventSourceHandler.onConnect(); } @Override public void onMessage(String event, MessageEvent message) throws Exception { + // pass event to the proper handler eventSourceHandler.onMessage(event, message); } @Override public void onError(Throwable t) { + // pass event to the proper handler eventSourceHandler.onError(t); } } diff --git a/src/main/java/com/github/eventsource/client/impl/netty/EventSourceChannelHandler.java b/src/main/java/com/github/eventsource/client/impl/netty/EventSourceChannelHandler.java index 809b70f..e630ba8 100644 --- a/src/main/java/com/github/eventsource/client/impl/netty/EventSourceChannelHandler.java +++ b/src/main/java/com/github/eventsource/client/impl/netty/EventSourceChannelHandler.java @@ -68,6 +68,7 @@ public void channelConnected(ChannelHandlerContext ctx, ChannelStateEvent e) thr if (lastEventId != null) { request.addHeader("Last-Event-ID", lastEventId); } + // add any custom headers that have been set for (String name : customRequestHeaders.keySet()) { request.addHeader(name, customRequestHeaders.get(name)); } @@ -156,6 +157,12 @@ public EventSourceChannelHandler join() throws InterruptedException { return this; } + /** + * Sets a custom HTTP header that will be used when the request is made to establish the SSE channel. + * + * @param name the HTTP header name + * @param value the header value + */ public void setCustomRequestHeader(String name, String value) { customRequestHeaders.put(name, value); } From 12e4c0bef712d5af6d455e24165f42776ea9f8b8 Mon Sep 17 00:00:00 2001 From: Dan Noguerol Date: Fri, 16 May 2014 17:41:46 -0600 Subject: [PATCH 04/17] Added SNAPSHOT to version. --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index c6ead51..b68bdd6 100644 --- a/pom.xml +++ b/pom.xml @@ -5,7 +5,7 @@ ${project.artifactId} A Java EventSource Client http://whizzosoftware.github.com/eventsource-java - 0.1.3 + 0.1.3-SNAPSHOT jar From 27587f7ff24a71613eb0afa4762a6971973ea8ee Mon Sep 17 00:00:00 2001 From: Dan Noguerol Date: Fri, 30 May 2014 08:32:48 -0600 Subject: [PATCH 05/17] From TomMettam: Add OnClosed event to notify if the eventsource gets dropped temporarily --- .../com/github/eventsource/client/EventSource.java | 5 +++++ .../eventsource/client/EventSourceHandler.java | 1 + .../client/impl/AsyncEventSourceHandler.java | 14 ++++++++++++++ .../impl/netty/EventSourceChannelHandler.java | 1 + .../eventsource/client/stubs/StubHandler.java | 5 +++++ 5 files changed, 26 insertions(+) diff --git a/src/main/java/com/github/eventsource/client/EventSource.java b/src/main/java/com/github/eventsource/client/EventSource.java index 31368d2..6f7566a 100644 --- a/src/main/java/com/github/eventsource/client/EventSource.java +++ b/src/main/java/com/github/eventsource/client/EventSource.java @@ -160,4 +160,9 @@ public void onError(Throwable t) { // pass event to the proper handler eventSourceHandler.onError(t); } + + @Override + public void onClosed(boolean willReconnect) { + eventSourceHandler.onClosed(willReconnect); + } } diff --git a/src/main/java/com/github/eventsource/client/EventSourceHandler.java b/src/main/java/com/github/eventsource/client/EventSourceHandler.java index b50b3d0..2ec35bf 100644 --- a/src/main/java/com/github/eventsource/client/EventSourceHandler.java +++ b/src/main/java/com/github/eventsource/client/EventSourceHandler.java @@ -4,4 +4,5 @@ public interface EventSourceHandler { void onConnect() throws Exception; void onMessage(String event, MessageEvent message) throws Exception; void onError(Throwable t); + void onClosed(boolean willReconnect); } diff --git a/src/main/java/com/github/eventsource/client/impl/AsyncEventSourceHandler.java b/src/main/java/com/github/eventsource/client/impl/AsyncEventSourceHandler.java index 89864f2..63f1943 100644 --- a/src/main/java/com/github/eventsource/client/impl/AsyncEventSourceHandler.java +++ b/src/main/java/com/github/eventsource/client/impl/AsyncEventSourceHandler.java @@ -55,4 +55,18 @@ public void run() { } }); } + + @Override + public void onClosed(final boolean willReconnect) { + executor.execute(new Runnable() { + @Override + public void run() { + try { + eventSourceHandler.onClosed(willReconnect); + } catch (Exception e) { + onError(e); + } + } + }); + } } diff --git a/src/main/java/com/github/eventsource/client/impl/netty/EventSourceChannelHandler.java b/src/main/java/com/github/eventsource/client/impl/netty/EventSourceChannelHandler.java index e630ba8..8ccbd46 100644 --- a/src/main/java/com/github/eventsource/client/impl/netty/EventSourceChannelHandler.java +++ b/src/main/java/com/github/eventsource/client/impl/netty/EventSourceChannelHandler.java @@ -83,6 +83,7 @@ public void channelDisconnected(ChannelHandlerContext ctx, ChannelStateEvent e) @Override public void channelClosed(ChannelHandlerContext ctx, ChannelStateEvent e) throws Exception { + eventSourceHandler.onClosed(reconnectOnClose); if (reconnectOnClose) { reconnect(); } diff --git a/src/main/java/com/github/eventsource/client/stubs/StubHandler.java b/src/main/java/com/github/eventsource/client/stubs/StubHandler.java index 5977afb..01856db 100644 --- a/src/main/java/com/github/eventsource/client/stubs/StubHandler.java +++ b/src/main/java/com/github/eventsource/client/stubs/StubHandler.java @@ -32,6 +32,11 @@ public void onConnect() throws Exception { connected = true; } + @Override + public void onClosed(boolean willReconnect){ + connected = false; + } + @Override public void onMessage(String event, MessageEvent message) throws Exception { getMessageEvents(event).add(message); From 5f7f2089b8a6ecae349e22c232529c69969f7316 Mon Sep 17 00:00:00 2001 From: Dan Noguerol Date: Fri, 30 May 2014 08:35:48 -0600 Subject: [PATCH 06/17] From TomMettam: Re-set the URI when reconnecting to avoid a perpetual unresolved address condition --- .../java/com/github/eventsource/client/EventSource.java | 6 ++++++ .../client/impl/netty/EventSourceChannelHandler.java | 2 ++ 2 files changed, 8 insertions(+) diff --git a/src/main/java/com/github/eventsource/client/EventSource.java b/src/main/java/com/github/eventsource/client/EventSource.java index 6f7566a..83a8ae8 100644 --- a/src/main/java/com/github/eventsource/client/EventSource.java +++ b/src/main/java/com/github/eventsource/client/EventSource.java @@ -31,6 +31,7 @@ public class EventSource implements EventSourceHandler { private final EventSourceChannelHandler clientHandler; private final EventSourceHandler eventSourceHandler; + private URI uri; private int readyState; /** @@ -57,6 +58,7 @@ public EventSource(Executor executor, long reconnectionTimeMillis, final URI uri new NioClientSocketChannelFactory( Executors.newSingleThreadExecutor(), Executors.newSingleThreadExecutor())); + this.uri = uri; bootstrap.setOption("remoteAddress", new InetSocketAddress(uri.getHost(), uri.getPort())); // add this class as the event source handler so the connect() call can be intercepted @@ -111,6 +113,10 @@ public void setCustomRequestHeader(String name, String value) { public ChannelFuture connect() { readyState = CONNECTING; + + //To avoid perpetual "SocketUnresolvedException" + bootstrap.setOption("remoteAddress", new InetSocketAddress(uri.getHost(), uri.getPort())); + return bootstrap.connect(); } diff --git a/src/main/java/com/github/eventsource/client/impl/netty/EventSourceChannelHandler.java b/src/main/java/com/github/eventsource/client/impl/netty/EventSourceChannelHandler.java index 8ccbd46..0093eea 100644 --- a/src/main/java/com/github/eventsource/client/impl/netty/EventSourceChannelHandler.java +++ b/src/main/java/com/github/eventsource/client/impl/netty/EventSourceChannelHandler.java @@ -17,6 +17,7 @@ import org.jboss.netty.util.TimerTask; import java.net.ConnectException; +import java.net.InetSocketAddress; import java.net.URI; import java.util.HashMap; import java.util.Map; @@ -175,6 +176,7 @@ private void reconnect() { @Override public void run(Timeout timeout) throws Exception { reconnecting.set(false); + bootstrap.setOption("remoteAddress", new InetSocketAddress(uri.getHost(), uri.getPort())); bootstrap.connect().await(); } }, reconnectionTimeMillis, TimeUnit.MILLISECONDS); From cc9a5fcc3ea48a12fa8faa3dfdb4f43e71066028 Mon Sep 17 00:00:00 2001 From: Dan Noguerol Date: Fri, 30 May 2014 08:41:52 -0600 Subject: [PATCH 07/17] From TomMettam: Calculate port based on schema if the port is not explicitly set. --- .../com/github/eventsource/client/EventSource.java | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/github/eventsource/client/EventSource.java b/src/main/java/com/github/eventsource/client/EventSource.java index 83a8ae8..7cac7c2 100644 --- a/src/main/java/com/github/eventsource/client/EventSource.java +++ b/src/main/java/com/github/eventsource/client/EventSource.java @@ -59,7 +59,8 @@ public EventSource(Executor executor, long reconnectionTimeMillis, final URI uri Executors.newSingleThreadExecutor(), Executors.newSingleThreadExecutor())); this.uri = uri; - bootstrap.setOption("remoteAddress", new InetSocketAddress(uri.getHost(), uri.getPort())); + + bootstrap.setOption("remoteAddress", new InetSocketAddress(uri.getHost(), getPort(uri))); // add this class as the event source handler so the connect() call can be intercepted AsyncEventSourceHandler asyncHandler = new AsyncEventSourceHandler(executor, this); @@ -115,7 +116,7 @@ public ChannelFuture connect() { readyState = CONNECTING; //To avoid perpetual "SocketUnresolvedException" - bootstrap.setOption("remoteAddress", new InetSocketAddress(uri.getHost(), uri.getPort())); + bootstrap.setOption("remoteAddress", new InetSocketAddress(uri.getHost(), getPort(uri))); return bootstrap.connect(); } @@ -171,4 +172,12 @@ public void onError(Throwable t) { public void onClosed(boolean willReconnect) { eventSourceHandler.onClosed(willReconnect); } + + protected int getPort(URI uri) { + int port = uri.getPort(); + if (port == -1) { + port = (uri.getScheme().equals("https")) ? 443 : 80; + } + return port; + } } From bddab8e667d06d3c36fe9b7456a95eed406cd8db Mon Sep 17 00:00:00 2001 From: Dan Noguerol Date: Fri, 30 May 2014 08:43:12 -0600 Subject: [PATCH 08/17] From TomMettam: Use the correct origin in the case of an SSL connection. --- .../client/impl/netty/EventSourceChannelHandler.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/github/eventsource/client/impl/netty/EventSourceChannelHandler.java b/src/main/java/com/github/eventsource/client/impl/netty/EventSourceChannelHandler.java index 0093eea..d670cf0 100644 --- a/src/main/java/com/github/eventsource/client/impl/netty/EventSourceChannelHandler.java +++ b/src/main/java/com/github/eventsource/client/impl/netty/EventSourceChannelHandler.java @@ -64,7 +64,7 @@ public void channelConnected(ChannelHandlerContext ctx, ChannelStateEvent e) thr HttpRequest request = new DefaultHttpRequest(HttpVersion.HTTP_1_1, HttpMethod.GET, uri.toString()); request.addHeader(Names.ACCEPT, "text/event-stream"); request.addHeader(Names.HOST, uri.getHost()); - request.addHeader(Names.ORIGIN, "http://" + uri.getHost()); + request.addHeader(Names.ORIGIN, uri.getScheme() + "://" + uri.getHost()); request.addHeader(Names.CACHE_CONTROL, "no-cache"); if (lastEventId != null) { request.addHeader("Last-Event-ID", lastEventId); From 4586077bd56f9ceab343e24f1c05cef72e43979b Mon Sep 17 00:00:00 2001 From: Dan Noguerol Date: Sat, 31 May 2014 18:43:35 -0600 Subject: [PATCH 09/17] Fixed unit test bug. --- src/test/java/com/github/eventsource/client/DebugClient.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/test/java/com/github/eventsource/client/DebugClient.java b/src/test/java/com/github/eventsource/client/DebugClient.java index 3c11876..5ce75fb 100644 --- a/src/test/java/com/github/eventsource/client/DebugClient.java +++ b/src/test/java/com/github/eventsource/client/DebugClient.java @@ -21,6 +21,11 @@ public void onError(Throwable t) { System.err.println("ERROR"); t.printStackTrace(); } + + @Override + public void onClosed(boolean willReconnect) { + System.err.println("CLOSED"); + } }); es.connect(); From cb669a9fafe4079ea24f08d6e18eaa2adf98091d Mon Sep 17 00:00:00 2001 From: Dan Noguerol Date: Sat, 31 May 2014 19:33:05 -0600 Subject: [PATCH 10/17] Added SSLEngineProvider interface so EventSource can re-create SSLEngine on reconnects. Thanks Tom for finding the bug! --- .../github/eventsource/client/EventSource.java | 17 +++++++++-------- .../eventsource/client/SSLEngineProvider.java | 7 +++++++ .../client/EventSourceClientTest.java | 9 +++++++++ 3 files changed, 25 insertions(+), 8 deletions(-) create mode 100644 src/main/java/com/github/eventsource/client/SSLEngineProvider.java diff --git a/src/main/java/com/github/eventsource/client/EventSource.java b/src/main/java/com/github/eventsource/client/EventSource.java index 7cac7c2..11d12ae 100644 --- a/src/main/java/com/github/eventsource/client/EventSource.java +++ b/src/main/java/com/github/eventsource/client/EventSource.java @@ -51,7 +51,7 @@ public EventSource(Executor executor, long reconnectionTimeMillis, final URI uri this(executor, reconnectionTimeMillis, uri, null, eventSourceHandler); } - public EventSource(Executor executor, long reconnectionTimeMillis, final URI uri, final SSLEngine sslEngine, EventSourceHandler eventSourceHandler) { + public EventSource(Executor executor, long reconnectionTimeMillis, final URI uri, final SSLEngineProvider sslEngineProvider, EventSourceHandler eventSourceHandler) { this.eventSourceHandler = eventSourceHandler; bootstrap = new ClientBootstrap( @@ -71,9 +71,10 @@ public EventSource(Executor executor, long reconnectionTimeMillis, final URI uri public ChannelPipeline getPipeline() throws Exception { ChannelPipeline pipeline = Channels.pipeline(); - if (sslEngine != null) { - sslEngine.setUseClientMode(true); - pipeline.addLast("ssl", new SslHandler(sslEngine)); + if (uri.getScheme().equals("https") && sslEngineProvider != null) { + SSLEngine engine = sslEngineProvider.createSSLEngine(); + engine.setUseClientMode(true); + pipeline.addLast("ssl", new SslHandler(engine)); } pipeline.addLast("line", new DelimiterBasedFrameDecoder(Integer.MAX_VALUE, Delimiters.lineDelimiter())); @@ -90,16 +91,16 @@ public EventSource(String uri, EventSourceHandler eventSourceHandler) { this(uri, null, eventSourceHandler); } - public EventSource(String uri, SSLEngine sslEngine, EventSourceHandler eventSourceHandler) { - this(URI.create(uri), sslEngine, eventSourceHandler); + public EventSource(String uri, SSLEngineProvider sslEngineProvider, EventSourceHandler eventSourceHandler) { + this(URI.create(uri), sslEngineProvider, eventSourceHandler); } public EventSource(URI uri, EventSourceHandler eventSourceHandler) { this(uri, null, eventSourceHandler); } - public EventSource(URI uri, SSLEngine sslEngine, EventSourceHandler eventSourceHandler) { - this(Executors.newSingleThreadExecutor(), DEFAULT_RECONNECTION_TIME_MILLIS, uri, sslEngine, eventSourceHandler); + public EventSource(URI uri, SSLEngineProvider sslEngineProvider, EventSourceHandler eventSourceHandler) { + this(Executors.newSingleThreadExecutor(), DEFAULT_RECONNECTION_TIME_MILLIS, uri, sslEngineProvider, eventSourceHandler); } /** diff --git a/src/main/java/com/github/eventsource/client/SSLEngineProvider.java b/src/main/java/com/github/eventsource/client/SSLEngineProvider.java new file mode 100644 index 0000000..9f6ac28 --- /dev/null +++ b/src/main/java/com/github/eventsource/client/SSLEngineProvider.java @@ -0,0 +1,7 @@ +package com.github.eventsource.client; + +import javax.net.ssl.SSLEngine; + +public interface SSLEngineProvider { + SSLEngine createSSLEngine(); +} \ No newline at end of file diff --git a/src/test/java/com/github/eventsource/client/EventSourceClientTest.java b/src/test/java/com/github/eventsource/client/EventSourceClientTest.java index 02fb54a..27c44d9 100644 --- a/src/test/java/com/github/eventsource/client/EventSourceClientTest.java +++ b/src/test/java/com/github/eventsource/client/EventSourceClientTest.java @@ -105,6 +105,11 @@ public void onError(Throwable t) { System.out.println("ERROR: " + t); errorCountdown.countDown(); } + + @Override + public void onClosed(boolean willReconnect) { + System.out.println("CLOSED"); + } }); eventSource.connect(); @@ -147,6 +152,10 @@ public void onMessage(String event, com.github.eventsource.client.MessageEvent m public void onError(Throwable t) { errorCountdown.countDown(); } + + @Override + public void onClosed(boolean willReconnect) { + } }); eventSource.connect().await(); } From 75ad78853286b788b73df50e61c04db72bf6654b Mon Sep 17 00:00:00 2001 From: Gavriel Fleischer Date: Fri, 1 Aug 2014 01:34:11 +0300 Subject: [PATCH 11/17] fixed GET to be path instead of full url --- .../impl/netty/EventSourceChannelHandler.java | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/src/main/java/com/github/eventsource/client/impl/netty/EventSourceChannelHandler.java b/src/main/java/com/github/eventsource/client/impl/netty/EventSourceChannelHandler.java index d670cf0..8846a58 100644 --- a/src/main/java/com/github/eventsource/client/impl/netty/EventSourceChannelHandler.java +++ b/src/main/java/com/github/eventsource/client/impl/netty/EventSourceChannelHandler.java @@ -5,7 +5,15 @@ import com.github.eventsource.client.impl.ConnectionHandler; import com.github.eventsource.client.impl.EventStreamParser; import org.jboss.netty.bootstrap.ClientBootstrap; -import org.jboss.netty.channel.*; + +import org.jboss.netty.channel.SimpleChannelUpstreamHandler; +import org.jboss.netty.channel.ChannelHandlerContext; +import org.jboss.netty.channel.Channel; +import org.jboss.netty.channel.ChannelEvent; +import org.jboss.netty.channel.ChannelStateEvent; +import org.jboss.netty.channel.MessageEvent; +import org.jboss.netty.channel.ExceptionEvent; + import org.jboss.netty.handler.codec.http.DefaultHttpRequest; import org.jboss.netty.handler.codec.http.HttpHeaders.Names; import org.jboss.netty.handler.codec.http.HttpMethod; @@ -61,7 +69,9 @@ public void handleUpstream(ChannelHandlerContext ctx, ChannelEvent e) throws Exc @Override public void channelConnected(ChannelHandlerContext ctx, ChannelStateEvent e) throws Exception { - HttpRequest request = new DefaultHttpRequest(HttpVersion.HTTP_1_1, HttpMethod.GET, uri.toString()); + final String query = uri.getQuery(); + final String path = uri.getPath() + (null != query && !query.isEmpty() ? "?" + query : ""); + final HttpRequest request = new DefaultHttpRequest(HttpVersion.HTTP_1_1, HttpMethod.GET, path); request.addHeader(Names.ACCEPT, "text/event-stream"); request.addHeader(Names.HOST, uri.getHost()); request.addHeader(Names.ORIGIN, uri.getScheme() + "://" + uri.getHost()); @@ -182,4 +192,4 @@ public void run(Timeout timeout) throws Exception { }, reconnectionTimeMillis, TimeUnit.MILLISECONDS); } } -} \ No newline at end of file +} From d20a9456bc1702885ba0ac7f78bc545458634be6 Mon Sep 17 00:00:00 2001 From: Gavriel Fleischer Date: Fri, 1 Aug 2014 01:35:14 +0300 Subject: [PATCH 12/17] added port to Host: and Origin: headers --- .../client/impl/netty/EventSourceChannelHandler.java | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/github/eventsource/client/impl/netty/EventSourceChannelHandler.java b/src/main/java/com/github/eventsource/client/impl/netty/EventSourceChannelHandler.java index 8846a58..31299a3 100644 --- a/src/main/java/com/github/eventsource/client/impl/netty/EventSourceChannelHandler.java +++ b/src/main/java/com/github/eventsource/client/impl/netty/EventSourceChannelHandler.java @@ -71,10 +71,13 @@ public void handleUpstream(ChannelHandlerContext ctx, ChannelEvent e) throws Exc public void channelConnected(ChannelHandlerContext ctx, ChannelStateEvent e) throws Exception { final String query = uri.getQuery(); final String path = uri.getPath() + (null != query && !query.isEmpty() ? "?" + query : ""); + final int port = uri.getPort(); + final String portPostfix = (port != 80 && port != 443) ? ":" + port : ""; + final String host = uri.getHost() + portPostfix; final HttpRequest request = new DefaultHttpRequest(HttpVersion.HTTP_1_1, HttpMethod.GET, path); request.addHeader(Names.ACCEPT, "text/event-stream"); - request.addHeader(Names.HOST, uri.getHost()); - request.addHeader(Names.ORIGIN, uri.getScheme() + "://" + uri.getHost()); + request.addHeader(Names.HOST, host); + request.addHeader(Names.ORIGIN, uri.getScheme() + "://" + host); request.addHeader(Names.CACHE_CONTROL, "no-cache"); if (lastEventId != null) { request.addHeader("Last-Event-ID", lastEventId); From bc93feb2b231447d3f07e5da844da8e537b1db67 Mon Sep 17 00:00:00 2001 From: Gavriel Fleischer Date: Fri, 1 Aug 2014 01:35:56 +0300 Subject: [PATCH 13/17] check Content-type case insensitively --- .../client/impl/netty/EventSourceChannelHandler.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/github/eventsource/client/impl/netty/EventSourceChannelHandler.java b/src/main/java/com/github/eventsource/client/impl/netty/EventSourceChannelHandler.java index 31299a3..646b137 100644 --- a/src/main/java/com/github/eventsource/client/impl/netty/EventSourceChannelHandler.java +++ b/src/main/java/com/github/eventsource/client/impl/netty/EventSourceChannelHandler.java @@ -36,7 +36,7 @@ public class EventSourceChannelHandler extends SimpleChannelUpstreamHandler implements ConnectionHandler { private static final Pattern STATUS_PATTERN = Pattern.compile("HTTP/1.1 (\\d+) (.*)"); - private static final Pattern CONTENT_TYPE_PATTERN = Pattern.compile("Content-Type: text/event-stream"); + private static final Pattern CONTENT_TYPE_PATTERN = Pattern.compile("Content-Type: text/event-stream", Pattern.CASE_INSENSITIVE); private final EventSourceHandler eventSourceHandler; private final ClientBootstrap bootstrap; From 59619f00cf5e509da470d5c981dec3437bbcf8e0 Mon Sep 17 00:00:00 2001 From: Gavriel Fleischer Date: Fri, 1 Aug 2014 01:36:44 +0300 Subject: [PATCH 14/17] use AtomicBoolean really atomically for reconnecting --- .../client/impl/netty/EventSourceChannelHandler.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/main/java/com/github/eventsource/client/impl/netty/EventSourceChannelHandler.java b/src/main/java/com/github/eventsource/client/impl/netty/EventSourceChannelHandler.java index 646b137..2dd77f7 100644 --- a/src/main/java/com/github/eventsource/client/impl/netty/EventSourceChannelHandler.java +++ b/src/main/java/com/github/eventsource/client/impl/netty/EventSourceChannelHandler.java @@ -183,8 +183,7 @@ public void setCustomRequestHeader(String name, String value) { } private void reconnect() { - if(!reconnecting.get()) { - reconnecting.set(true); + if (reconnecting.compareAndSet(false, true)) { timer.newTimeout(new TimerTask() { @Override public void run(Timeout timeout) throws Exception { From 08864d1a77640875a2280014cb0566014e200068 Mon Sep 17 00:00:00 2001 From: Gavriel Fleischer Date: Fri, 1 Aug 2014 01:37:34 +0300 Subject: [PATCH 15/17] call onConnect event also when reconnecting after error --- .../client/impl/netty/EventSourceChannelHandler.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/main/java/com/github/eventsource/client/impl/netty/EventSourceChannelHandler.java b/src/main/java/com/github/eventsource/client/impl/netty/EventSourceChannelHandler.java index 2dd77f7..6fdea53 100644 --- a/src/main/java/com/github/eventsource/client/impl/netty/EventSourceChannelHandler.java +++ b/src/main/java/com/github/eventsource/client/impl/netty/EventSourceChannelHandler.java @@ -184,6 +184,8 @@ public void setCustomRequestHeader(String name, String value) { private void reconnect() { if (reconnecting.compareAndSet(false, true)) { + headerDone = false; + eventStreamOk = false; timer.newTimeout(new TimerTask() { @Override public void run(Timeout timeout) throws Exception { From 6cf8180f63479b2c187eff59b29839fa4c8bffea Mon Sep 17 00:00:00 2001 From: Gavriel Fleischer Date: Fri, 1 Aug 2014 01:38:20 +0300 Subject: [PATCH 16/17] call onClosed only if it was successfully opened (and onConnect was called previously) --- .../client/impl/netty/EventSourceChannelHandler.java | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/github/eventsource/client/impl/netty/EventSourceChannelHandler.java b/src/main/java/com/github/eventsource/client/impl/netty/EventSourceChannelHandler.java index 6fdea53..f71c507 100644 --- a/src/main/java/com/github/eventsource/client/impl/netty/EventSourceChannelHandler.java +++ b/src/main/java/com/github/eventsource/client/impl/netty/EventSourceChannelHandler.java @@ -97,7 +97,10 @@ public void channelDisconnected(ChannelHandlerContext ctx, ChannelStateEvent e) @Override public void channelClosed(ChannelHandlerContext ctx, ChannelStateEvent e) throws Exception { - eventSourceHandler.onClosed(reconnectOnClose); + if (eventStreamOk) { + // call onClosed only if it was successfully opened (and onConnect was called) + eventSourceHandler.onClosed(reconnectOnClose); + } if (reconnectOnClose) { reconnect(); } From af1322c1c8f7ebbd574eb65044dbfbfa60a419d1 Mon Sep 17 00:00:00 2001 From: Gavriel Fleischer Date: Fri, 1 Aug 2014 06:39:31 +0300 Subject: [PATCH 17/17] fixed port:-1 --- .../client/impl/netty/EventSourceChannelHandler.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/github/eventsource/client/impl/netty/EventSourceChannelHandler.java b/src/main/java/com/github/eventsource/client/impl/netty/EventSourceChannelHandler.java index f71c507..0a7f669 100644 --- a/src/main/java/com/github/eventsource/client/impl/netty/EventSourceChannelHandler.java +++ b/src/main/java/com/github/eventsource/client/impl/netty/EventSourceChannelHandler.java @@ -70,9 +70,9 @@ public void handleUpstream(ChannelHandlerContext ctx, ChannelEvent e) throws Exc @Override public void channelConnected(ChannelHandlerContext ctx, ChannelStateEvent e) throws Exception { final String query = uri.getQuery(); - final String path = uri.getPath() + (null != query && !query.isEmpty() ? "?" + query : ""); + final String path = uri.getPath() + (((null != query) && !query.isEmpty()) ? "?" + query : ""); final int port = uri.getPort(); - final String portPostfix = (port != 80 && port != 443) ? ":" + port : ""; + final String portPostfix = ((port != -1) ? ":" + port : ""); final String host = uri.getHost() + portPostfix; final HttpRequest request = new DefaultHttpRequest(HttpVersion.HTTP_1_1, HttpMethod.GET, path); request.addHeader(Names.ACCEPT, "text/event-stream");