From d86f51fda0c0f74e2d66f9aea09f430ce0c55c89 Mon Sep 17 00:00:00 2001 From: b95500517 Date: Sun, 1 Mar 2015 07:39:26 +0800 Subject: [PATCH 1/7] replace Java-WebSocket to OkHttp WebSocket --- pom.xml | 10 +- .../engineio/client/transports/WebSocket.java | 194 ++++++++++-------- 2 files changed, 119 insertions(+), 85 deletions(-) diff --git a/pom.xml b/pom.xml index 9c4f82d..735d9b5 100644 --- a/pom.xml +++ b/pom.xml @@ -47,11 +47,6 @@ json 20090211 - - org.java-websocket - Java-WebSocket - 1.3.0 - junit junit @@ -64,6 +59,11 @@ 1.3 test + + com.squareup.okhttp + okhttp-ws + 2.3.0 + diff --git a/src/main/java/com/github/nkzawa/engineio/client/transports/WebSocket.java b/src/main/java/com/github/nkzawa/engineio/client/transports/WebSocket.java index f7a8c88..39bb458 100644 --- a/src/main/java/com/github/nkzawa/engineio/client/transports/WebSocket.java +++ b/src/main/java/com/github/nkzawa/engineio/client/transports/WebSocket.java @@ -6,22 +6,31 @@ import com.github.nkzawa.engineio.parser.Packet; import com.github.nkzawa.engineio.parser.Parser; import com.github.nkzawa.parseqs.ParseQS; import com.github.nkzawa.thread.EventThread; -import org.java_websocket.client.DefaultSSLWebSocketClientFactory; -import org.java_websocket.client.WebSocketClient; -import org.java_websocket.drafts.Draft_17; -import org.java_websocket.handshake.ServerHandshake; +import com.squareup.okhttp.OkHttpClient; +import com.squareup.okhttp.Request; +import com.squareup.okhttp.Response; +import com.squareup.okhttp.ws.WebSocket.PayloadType; +import com.squareup.okhttp.ws.WebSocketCall; +import com.squareup.okhttp.ws.WebSocketListener; -import java.net.URI; -import java.net.URISyntaxException; -import java.nio.ByteBuffer; -import java.util.*; +import java.io.IOException; +import java.util.Date; +import java.util.HashMap; +import java.util.Map; +import java.util.TreeMap; + +import javax.net.ssl.SSLSocketFactory; + +import okio.Buffer; +import okio.BufferedSource; + +import static com.squareup.okhttp.ws.WebSocket.PayloadType.BINARY; +import static com.squareup.okhttp.ws.WebSocket.PayloadType.TEXT; public class WebSocket extends Transport { public static final String NAME = "websocket"; - - private WebSocketClient ws; - + private com.squareup.okhttp.ws.WebSocket ws; public WebSocket(Options opts) { super(opts); @@ -37,70 +46,87 @@ public class WebSocket extends Transport { this.emit(EVENT_REQUEST_HEADERS, headers); final WebSocket self = this; - try { - this.ws = new WebSocketClient(new URI(this.uri()), new Draft_17(), headers, 0) { - @Override - public void onOpen(final ServerHandshake serverHandshake) { - EventThread.exec(new Runnable() { - @Override - public void run() { - Map headers = new TreeMap(String.CASE_INSENSITIVE_ORDER); - Iterator it = serverHandshake.iterateHttpFields(); - while (it.hasNext()) { - String field = it.next(); - if (field == null) continue; - headers.put(field, serverHandshake.getFieldValue(field)); - } - self.emit(EVENT_RESPONSE_HEADERS, headers); - - self.onOpen(); - } - }); - } - @Override - public void onClose(int i, String s, boolean b) { - EventThread.exec(new Runnable() { - @Override - public void run() { - self.onClose(); - } - }); - } - @Override - public void onMessage(final String s) { - EventThread.exec(new Runnable() { - @Override - public void run() { - self.onData(s); - } - }); - } - @Override - public void onMessage(final ByteBuffer s) { - EventThread.exec(new Runnable() { - @Override - public void run() { - self.onData(s.array()); - } - }); - } - @Override - public void onError(final Exception e) { - EventThread.exec(new Runnable() { - @Override - public void run() { - self.onError("websocket error", e); - } - }); - } - }; - if (this.sslContext != null) { - this.ws.setWebSocketFactory(new DefaultSSLWebSocketClientFactory(this.sslContext)); - } - this.ws.connect(); - } catch (URISyntaxException e) { - throw new RuntimeException(e); + final OkHttpClient client = new OkHttpClient(); + if (this.sslContext != null) { + SSLSocketFactory factory = sslContext.getSocketFactory();// (SSLSocketFactory) SSLSocketFactory.getDefault(); + client.setSslSocketFactory(factory); } + final Request request = new Request.Builder() + .url(uri()) + .build(); + WebSocketCall.create(client, request).enqueue(new WebSocketListener() { + @Override + public void onOpen(com.squareup.okhttp.ws.WebSocket webSocket, Request request, Response response) throws IOException { + ws = webSocket; + final Map headers = new TreeMap(String.CASE_INSENSITIVE_ORDER); + for (int i = 0, size = response.headers().size(); i < size; i++) { + headers.put(response.headers().name(i), response.headers().value(i)); + } + EventThread.exec(new Runnable() { + @Override + public void run() { + self.emit(EVENT_RESPONSE_HEADERS, headers); + self.onOpen(); + } + }); + } + + @Override + public void onMessage(BufferedSource payload, PayloadType type) throws IOException { + Object data; + switch (type) { + case TEXT: + data = payload.readUtf8(); + break; + case BINARY: + data = payload.readByteArray(); + break; + default: + throw new IllegalStateException("Unknown payload type: " + type); + } + payload.close(); + final Object finalData = data; + EventThread.exec(new Runnable() { + @Override + public void run() { + if (finalData == null) { + return; + } + if (finalData instanceof String) { + self.onData((String) finalData); + } else { + self.onData((byte[]) finalData); + } + } + }); + + } + + @Override + public void onPong(Buffer payload) { + } + + @Override + public void onClose(int code, String reason) { + EventThread.exec(new Runnable() { + @Override + public void run() { + self.onClose(); + } + }); + } + + @Override + public void onFailure(final IOException e) { + EventThread.exec(new Runnable() { + @Override + public void run() { + self.onError("websocket error", e); + } + }); + } + }); + client.getDispatcher().getExecutorService().shutdown(); } protected void write(Packet[] packets) { @@ -110,10 +136,14 @@ public class WebSocket extends Transport { Parser.encodePacket(packet, new Parser.EncodeCallback() { @Override public void call(Object packet) { - if (packet instanceof String) { - self.ws.send((String) packet); - } else if (packet instanceof byte[]) { - self.ws.send((byte[]) packet); + try { + if (packet instanceof String) { + self.ws.sendMessage(TEXT, new Buffer().writeUtf8((String) packet)); + } else if (packet instanceof byte[]) { + self.ws.sendMessage(BINARY, new Buffer().write((byte[]) packet)); + } + } catch (IOException e) { + e.printStackTrace(); } } }); @@ -139,7 +169,11 @@ public class WebSocket extends Transport { protected void doClose() { if (this.ws != null) { - this.ws.close(); + try { + this.ws.close(1000, ""); + } catch (IOException e) { + e.printStackTrace(); + } } } @@ -173,4 +207,4 @@ public class WebSocket extends Transport { return true; } -} +} \ No newline at end of file From b3586bb0b1f92ef84eaa0b10ff23d2610a385f84 Mon Sep 17 00:00:00 2001 From: Yu-Hsuan Lin Date: Mon, 13 Apr 2015 01:11:35 +0800 Subject: [PATCH 2/7] handle error using onError --- .../engineio/client/transports/WebSocket.java | 21 ++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/src/main/java/com/github/nkzawa/engineio/client/transports/WebSocket.java b/src/main/java/com/github/nkzawa/engineio/client/transports/WebSocket.java index 39bb458..29572a2 100644 --- a/src/main/java/com/github/nkzawa/engineio/client/transports/WebSocket.java +++ b/src/main/java/com/github/nkzawa/engineio/client/transports/WebSocket.java @@ -6,6 +6,7 @@ import com.github.nkzawa.engineio.parser.Packet; import com.github.nkzawa.engineio.parser.Parser; import com.github.nkzawa.parseqs.ParseQS; import com.github.nkzawa.thread.EventThread; +import com.squareup.okhttp.Headers; import com.squareup.okhttp.OkHttpClient; import com.squareup.okhttp.Request; import com.squareup.okhttp.Response; @@ -59,8 +60,9 @@ public class WebSocket extends Transport { public void onOpen(com.squareup.okhttp.ws.WebSocket webSocket, Request request, Response response) throws IOException { ws = webSocket; final Map headers = new TreeMap(String.CASE_INSENSITIVE_ORDER); - for (int i = 0, size = response.headers().size(); i < size; i++) { - headers.put(response.headers().name(i), response.headers().value(i)); + Headers responseHeaders = response.headers(); + for (int i = 0, size = responseHeaders.size(); i < size; i++) { + headers.put(responseHeaders.name(i), responseHeaders.value(i)); } EventThread.exec(new Runnable() { @Override @@ -72,8 +74,8 @@ public class WebSocket extends Transport { } @Override - public void onMessage(BufferedSource payload, PayloadType type) throws IOException { - Object data; + public void onMessage(BufferedSource payload, final PayloadType type) throws IOException { + Object data = null; switch (type) { case TEXT: data = payload.readUtf8(); @@ -82,7 +84,12 @@ public class WebSocket extends Transport { data = payload.readByteArray(); break; default: - throw new IllegalStateException("Unknown payload type: " + type); + EventThread.exec(new Runnable() { + @Override + public void run() { + self.onError("Unknown payload type: " + type, new IllegalStateException()); + } + }); } payload.close(); final Object finalData = data; @@ -143,7 +150,7 @@ public class WebSocket extends Transport { self.ws.sendMessage(BINARY, new Buffer().write((byte[]) packet)); } } catch (IOException e) { - e.printStackTrace(); + self.onError("websocket error", e); } } }); @@ -172,7 +179,7 @@ public class WebSocket extends Transport { try { this.ws.close(1000, ""); } catch (IOException e) { - e.printStackTrace(); + onError("doClose error", e); } } } From 3ccc42ab2c0060715f2857703cb5561373772cc8 Mon Sep 17 00:00:00 2001 From: Yu-Hsuan Lin Date: Mon, 13 Apr 2015 04:01:04 +0800 Subject: [PATCH 3/7] add request header, cancel WebSocketCall --- .../engineio/client/transports/WebSocket.java | 20 +++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/src/main/java/com/github/nkzawa/engineio/client/transports/WebSocket.java b/src/main/java/com/github/nkzawa/engineio/client/transports/WebSocket.java index 29572a2..e33f975 100644 --- a/src/main/java/com/github/nkzawa/engineio/client/transports/WebSocket.java +++ b/src/main/java/com/github/nkzawa/engineio/client/transports/WebSocket.java @@ -32,6 +32,7 @@ public class WebSocket extends Transport { public static final String NAME = "websocket"; private com.squareup.okhttp.ws.WebSocket ws; + private WebSocketCall wsCall; public WebSocket(Options opts) { super(opts); @@ -52,10 +53,12 @@ public class WebSocket extends Transport { SSLSocketFactory factory = sslContext.getSocketFactory();// (SSLSocketFactory) SSLSocketFactory.getDefault(); client.setSslSocketFactory(factory); } - final Request request = new Request.Builder() - .url(uri()) - .build(); - WebSocketCall.create(client, request).enqueue(new WebSocketListener() { + Request.Builder builder = new Request.Builder().url(uri()); + for (Map.Entry entry : headers.entrySet()) { + builder.addHeader(entry.getKey(), entry.getValue()); + } + final Request request = builder.build(); + (wsCall = WebSocketCall.create(client, request)).enqueue(new WebSocketListener() { @Override public void onOpen(com.squareup.okhttp.ws.WebSocket webSocket, Request request, Response response) throws IOException { ws = webSocket; @@ -175,12 +178,17 @@ public class WebSocket extends Transport { } protected void doClose() { - if (this.ws != null) { + if (wsCall != null) { + wsCall.cancel(); + wsCall = null; + } + if (ws != null) { try { - this.ws.close(1000, ""); + ws.close(1000, ""); } catch (IOException e) { onError("doClose error", e); } + ws = null; } } From 464b7302d42a5541975d50053c249fa450b840a3 Mon Sep 17 00:00:00 2001 From: Yu-Hsuan Lin Date: Tue, 14 Apr 2015 11:57:56 +0800 Subject: [PATCH 4/7] add new Options for feeding custom OkHttpClient --- pom.xml | 5 ++ .../github/nkzawa/engineio/client/Socket.java | 5 ++ .../nkzawa/engineio/client/Transport.java | 4 ++ .../engineio/client/transports/WebSocket.java | 2 +- .../engineio/client/SSLConnectionTest.java | 56 +++++++------------ 5 files changed, 34 insertions(+), 38 deletions(-) diff --git a/pom.xml b/pom.xml index 735d9b5..25e03e9 100644 --- a/pom.xml +++ b/pom.xml @@ -64,6 +64,11 @@ okhttp-ws 2.3.0 + + com.squareup.okhttp + mockwebserver + 2.3.0 + diff --git a/src/main/java/com/github/nkzawa/engineio/client/Socket.java b/src/main/java/com/github/nkzawa/engineio/client/Socket.java index ac37fef..97d40eb 100644 --- a/src/main/java/com/github/nkzawa/engineio/client/Socket.java +++ b/src/main/java/com/github/nkzawa/engineio/client/Socket.java @@ -8,6 +8,8 @@ import com.github.nkzawa.engineio.parser.Packet; import com.github.nkzawa.engineio.parser.Parser; import com.github.nkzawa.parseqs.ParseQS; import com.github.nkzawa.thread.EventThread; +import com.squareup.okhttp.OkHttpClient; + import org.json.JSONException; import javax.net.ssl.SSLContext; @@ -121,6 +123,7 @@ public class Socket extends Emitter { private Future pingTimeoutTimer; private Future pingIntervalTimer; private SSLContext sslContext; + private OkHttpClient okHttpClient; private ReadyState readyState; private ScheduledExecutorService heartbeatScheduler; @@ -197,6 +200,7 @@ public class Socket extends Emitter { opts.transports : new String[]{Polling.NAME, WebSocket.NAME})); this.policyPort = opts.policyPort != 0 ? opts.policyPort : 843; this.rememberUpgrade = opts.rememberUpgrade; + this.okHttpClient = opts.okHttpClient; } /** @@ -254,6 +258,7 @@ public class Socket extends Emitter { opts.timestampParam = this.timestampParam; opts.policyPort = this.policyPort; opts.socket = this; + opts.okHttpClient = this.okHttpClient; if (WebSocket.NAME.equals(name)) { return new WebSocket(opts); diff --git a/src/main/java/com/github/nkzawa/engineio/client/Transport.java b/src/main/java/com/github/nkzawa/engineio/client/Transport.java index 8277075..d0c6f9c 100644 --- a/src/main/java/com/github/nkzawa/engineio/client/Transport.java +++ b/src/main/java/com/github/nkzawa/engineio/client/Transport.java @@ -5,6 +5,7 @@ import com.github.nkzawa.emitter.Emitter; import com.github.nkzawa.engineio.parser.Packet; import com.github.nkzawa.engineio.parser.Parser; import com.github.nkzawa.thread.EventThread; +import com.squareup.okhttp.OkHttpClient; import javax.net.ssl.SSLContext; import java.util.Map; @@ -42,6 +43,7 @@ public abstract class Transport extends Emitter { protected String timestampParam; protected SSLContext sslContext; protected Socket socket; + protected OkHttpClient okHttpClient; protected ReadyState readyState; @@ -55,6 +57,7 @@ public abstract class Transport extends Emitter { this.timestampRequests = opts.timestampRequests; this.sslContext = opts.sslContext; this.socket = opts.socket; + this.okHttpClient = opts.okHttpClient; } protected Transport onError(String msg, Exception desc) { @@ -144,6 +147,7 @@ public abstract class Transport extends Emitter { public int policyPort = -1; public Map query; public SSLContext sslContext; + public OkHttpClient okHttpClient; protected Socket socket; } } diff --git a/src/main/java/com/github/nkzawa/engineio/client/transports/WebSocket.java b/src/main/java/com/github/nkzawa/engineio/client/transports/WebSocket.java index e33f975..6331e13 100644 --- a/src/main/java/com/github/nkzawa/engineio/client/transports/WebSocket.java +++ b/src/main/java/com/github/nkzawa/engineio/client/transports/WebSocket.java @@ -48,7 +48,7 @@ public class WebSocket extends Transport { this.emit(EVENT_REQUEST_HEADERS, headers); final WebSocket self = this; - final OkHttpClient client = new OkHttpClient(); + final OkHttpClient client = this.okHttpClient != null ? this.okHttpClient : new OkHttpClient(); if (this.sslContext != null) { SSLSocketFactory factory = sslContext.getSocketFactory();// (SSLSocketFactory) SSLSocketFactory.getDefault(); client.setSslSocketFactory(factory); diff --git a/src/test/java/com/github/nkzawa/engineio/client/SSLConnectionTest.java b/src/test/java/com/github/nkzawa/engineio/client/SSLConnectionTest.java index c4c0e5c..c50b3c8 100644 --- a/src/test/java/com/github/nkzawa/engineio/client/SSLConnectionTest.java +++ b/src/test/java/com/github/nkzawa/engineio/client/SSLConnectionTest.java @@ -1,37 +1,31 @@ package com.github.nkzawa.engineio.client; import com.github.nkzawa.emitter.Emitter; +import com.squareup.okhttp.OkHttpClient; +import com.squareup.okhttp.internal.SslContextBuilder; + import org.junit.After; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.JUnit4; -import javax.net.ssl.KeyManagerFactory; -import javax.net.ssl.SSLContext; -import javax.net.ssl.TrustManagerFactory; -import java.io.File; -import java.io.FileInputStream; -import java.io.IOException; -import java.security.GeneralSecurityException; -import java.security.KeyStore; import java.util.concurrent.BlockingQueue; import java.util.concurrent.LinkedBlockingQueue; +import javax.net.ssl.HostnameVerifier; + import static org.hamcrest.CoreMatchers.is; import static org.junit.Assert.assertThat; @RunWith(JUnit4.class) public class SSLConnectionTest extends Connection { - static { - // for test on localhost - javax.net.ssl.HttpsURLConnection.setDefaultHostnameVerifier( - new javax.net.ssl.HostnameVerifier(){ - public boolean verify(String hostname, javax.net.ssl.SSLSession sslSession) { - return hostname.equals("localhost"); - } - }); - } + static HostnameVerifier hostnameVerifier = new javax.net.ssl.HostnameVerifier(){ + public boolean verify(String hostname, javax.net.ssl.SSLSession sslSession) { + return true; + } + }; + private Socket socket; @@ -52,28 +46,13 @@ public class SSLConnectionTest extends Connection { return new String[] {"DEBUG=engine*", "PORT=" + PORT, "SSL=1"}; } - SSLContext createSSLContext() throws GeneralSecurityException, IOException { - KeyStore ks = KeyStore.getInstance("JKS"); - File file = new File("src/test/resources/keystore.jks"); - ks.load(new FileInputStream(file), "password".toCharArray()); - - KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509"); - kmf.init(ks, "password".toCharArray()); - - TrustManagerFactory tmf = TrustManagerFactory.getInstance("SunX509"); - tmf.init(ks); - - SSLContext sslContext = SSLContext.getInstance("TLS"); - sslContext.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null); - return sslContext; - } - @Test(timeout = TIMEOUT) public void connect() throws Exception { final BlockingQueue values = new LinkedBlockingQueue(); Socket.Options opts = createOptions(); - opts.sslContext = createSSLContext(); + opts.sslContext = SslContextBuilder.localhost(); + opts.okHttpClient = new OkHttpClient().setHostnameVerifier(hostnameVerifier); socket = new Socket(opts); socket.on(Socket.EVENT_OPEN, new Emitter.Listener() { @Override @@ -97,7 +76,8 @@ public class SSLConnectionTest extends Connection { final BlockingQueue values = new LinkedBlockingQueue(); Socket.Options opts = createOptions(); - opts.sslContext = createSSLContext(); + opts.sslContext = SslContextBuilder.localhost(); + opts.okHttpClient = new OkHttpClient().setHostnameVerifier(hostnameVerifier); socket = new Socket(opts); socket.on(Socket.EVENT_OPEN, new Emitter.Listener() { @Override @@ -126,8 +106,10 @@ public class SSLConnectionTest extends Connection { public void defaultSSLContext() throws Exception { final BlockingQueue values = new LinkedBlockingQueue(); - Socket.setDefaultSSLContext(createSSLContext()); - socket = new Socket(createOptions()); + Socket.Options opts = createOptions(); + Socket.setDefaultSSLContext(SslContextBuilder.localhost()); + opts.okHttpClient = new OkHttpClient().setHostnameVerifier(hostnameVerifier); + socket = new Socket(opts); socket.on(Socket.EVENT_OPEN, new Emitter.Listener() { @Override public void call(Object... args) { From 822aaebc351c604bcde4b0475613ee200efe0aae Mon Sep 17 00:00:00 2001 From: Yu-Hsuan Lin Date: Sat, 2 May 2015 00:59:34 +0800 Subject: [PATCH 5/7] Revert "add new Options for feeding custom OkHttpClient" This reverts commit 464b7302d42a5541975d50053c249fa450b840a3. --- pom.xml | 5 -- .../github/nkzawa/engineio/client/Socket.java | 5 -- .../nkzawa/engineio/client/Transport.java | 4 -- .../engineio/client/transports/WebSocket.java | 2 +- .../engineio/client/SSLConnectionTest.java | 56 ++++++++++++------- 5 files changed, 38 insertions(+), 34 deletions(-) diff --git a/pom.xml b/pom.xml index 25e03e9..735d9b5 100644 --- a/pom.xml +++ b/pom.xml @@ -64,11 +64,6 @@ okhttp-ws 2.3.0 - - com.squareup.okhttp - mockwebserver - 2.3.0 - diff --git a/src/main/java/com/github/nkzawa/engineio/client/Socket.java b/src/main/java/com/github/nkzawa/engineio/client/Socket.java index 27796bf..4da61a6 100644 --- a/src/main/java/com/github/nkzawa/engineio/client/Socket.java +++ b/src/main/java/com/github/nkzawa/engineio/client/Socket.java @@ -8,8 +8,6 @@ import com.github.nkzawa.engineio.parser.Packet; import com.github.nkzawa.engineio.parser.Parser; import com.github.nkzawa.parseqs.ParseQS; import com.github.nkzawa.thread.EventThread; -import com.squareup.okhttp.OkHttpClient; - import org.json.JSONException; import javax.net.ssl.SSLContext; @@ -123,7 +121,6 @@ public class Socket extends Emitter { private Future pingTimeoutTimer; private Future pingIntervalTimer; private SSLContext sslContext; - private OkHttpClient okHttpClient; private ReadyState readyState; private ScheduledExecutorService heartbeatScheduler; @@ -200,7 +197,6 @@ public class Socket extends Emitter { opts.transports : new String[]{Polling.NAME, WebSocket.NAME})); this.policyPort = opts.policyPort != 0 ? opts.policyPort : 843; this.rememberUpgrade = opts.rememberUpgrade; - this.okHttpClient = opts.okHttpClient; } /** @@ -258,7 +254,6 @@ public class Socket extends Emitter { opts.timestampParam = this.timestampParam; opts.policyPort = this.policyPort; opts.socket = this; - opts.okHttpClient = this.okHttpClient; Transport transport; if (WebSocket.NAME.equals(name)) { diff --git a/src/main/java/com/github/nkzawa/engineio/client/Transport.java b/src/main/java/com/github/nkzawa/engineio/client/Transport.java index d0c6f9c..8277075 100644 --- a/src/main/java/com/github/nkzawa/engineio/client/Transport.java +++ b/src/main/java/com/github/nkzawa/engineio/client/Transport.java @@ -5,7 +5,6 @@ import com.github.nkzawa.emitter.Emitter; import com.github.nkzawa.engineio.parser.Packet; import com.github.nkzawa.engineio.parser.Parser; import com.github.nkzawa.thread.EventThread; -import com.squareup.okhttp.OkHttpClient; import javax.net.ssl.SSLContext; import java.util.Map; @@ -43,7 +42,6 @@ public abstract class Transport extends Emitter { protected String timestampParam; protected SSLContext sslContext; protected Socket socket; - protected OkHttpClient okHttpClient; protected ReadyState readyState; @@ -57,7 +55,6 @@ public abstract class Transport extends Emitter { this.timestampRequests = opts.timestampRequests; this.sslContext = opts.sslContext; this.socket = opts.socket; - this.okHttpClient = opts.okHttpClient; } protected Transport onError(String msg, Exception desc) { @@ -147,7 +144,6 @@ public abstract class Transport extends Emitter { public int policyPort = -1; public Map query; public SSLContext sslContext; - public OkHttpClient okHttpClient; protected Socket socket; } } diff --git a/src/main/java/com/github/nkzawa/engineio/client/transports/WebSocket.java b/src/main/java/com/github/nkzawa/engineio/client/transports/WebSocket.java index 6331e13..e33f975 100644 --- a/src/main/java/com/github/nkzawa/engineio/client/transports/WebSocket.java +++ b/src/main/java/com/github/nkzawa/engineio/client/transports/WebSocket.java @@ -48,7 +48,7 @@ public class WebSocket extends Transport { this.emit(EVENT_REQUEST_HEADERS, headers); final WebSocket self = this; - final OkHttpClient client = this.okHttpClient != null ? this.okHttpClient : new OkHttpClient(); + final OkHttpClient client = new OkHttpClient(); if (this.sslContext != null) { SSLSocketFactory factory = sslContext.getSocketFactory();// (SSLSocketFactory) SSLSocketFactory.getDefault(); client.setSslSocketFactory(factory); diff --git a/src/test/java/com/github/nkzawa/engineio/client/SSLConnectionTest.java b/src/test/java/com/github/nkzawa/engineio/client/SSLConnectionTest.java index c50b3c8..c4c0e5c 100644 --- a/src/test/java/com/github/nkzawa/engineio/client/SSLConnectionTest.java +++ b/src/test/java/com/github/nkzawa/engineio/client/SSLConnectionTest.java @@ -1,31 +1,37 @@ package com.github.nkzawa.engineio.client; import com.github.nkzawa.emitter.Emitter; -import com.squareup.okhttp.OkHttpClient; -import com.squareup.okhttp.internal.SslContextBuilder; - import org.junit.After; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.JUnit4; +import javax.net.ssl.KeyManagerFactory; +import javax.net.ssl.SSLContext; +import javax.net.ssl.TrustManagerFactory; +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.security.GeneralSecurityException; +import java.security.KeyStore; import java.util.concurrent.BlockingQueue; import java.util.concurrent.LinkedBlockingQueue; -import javax.net.ssl.HostnameVerifier; - import static org.hamcrest.CoreMatchers.is; import static org.junit.Assert.assertThat; @RunWith(JUnit4.class) public class SSLConnectionTest extends Connection { - static HostnameVerifier hostnameVerifier = new javax.net.ssl.HostnameVerifier(){ - public boolean verify(String hostname, javax.net.ssl.SSLSession sslSession) { - return true; - } - }; - + static { + // for test on localhost + javax.net.ssl.HttpsURLConnection.setDefaultHostnameVerifier( + new javax.net.ssl.HostnameVerifier(){ + public boolean verify(String hostname, javax.net.ssl.SSLSession sslSession) { + return hostname.equals("localhost"); + } + }); + } private Socket socket; @@ -46,13 +52,28 @@ public class SSLConnectionTest extends Connection { return new String[] {"DEBUG=engine*", "PORT=" + PORT, "SSL=1"}; } + SSLContext createSSLContext() throws GeneralSecurityException, IOException { + KeyStore ks = KeyStore.getInstance("JKS"); + File file = new File("src/test/resources/keystore.jks"); + ks.load(new FileInputStream(file), "password".toCharArray()); + + KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509"); + kmf.init(ks, "password".toCharArray()); + + TrustManagerFactory tmf = TrustManagerFactory.getInstance("SunX509"); + tmf.init(ks); + + SSLContext sslContext = SSLContext.getInstance("TLS"); + sslContext.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null); + return sslContext; + } + @Test(timeout = TIMEOUT) public void connect() throws Exception { final BlockingQueue values = new LinkedBlockingQueue(); Socket.Options opts = createOptions(); - opts.sslContext = SslContextBuilder.localhost(); - opts.okHttpClient = new OkHttpClient().setHostnameVerifier(hostnameVerifier); + opts.sslContext = createSSLContext(); socket = new Socket(opts); socket.on(Socket.EVENT_OPEN, new Emitter.Listener() { @Override @@ -76,8 +97,7 @@ public class SSLConnectionTest extends Connection { final BlockingQueue values = new LinkedBlockingQueue(); Socket.Options opts = createOptions(); - opts.sslContext = SslContextBuilder.localhost(); - opts.okHttpClient = new OkHttpClient().setHostnameVerifier(hostnameVerifier); + opts.sslContext = createSSLContext(); socket = new Socket(opts); socket.on(Socket.EVENT_OPEN, new Emitter.Listener() { @Override @@ -106,10 +126,8 @@ public class SSLConnectionTest extends Connection { public void defaultSSLContext() throws Exception { final BlockingQueue values = new LinkedBlockingQueue(); - Socket.Options opts = createOptions(); - Socket.setDefaultSSLContext(SslContextBuilder.localhost()); - opts.okHttpClient = new OkHttpClient().setHostnameVerifier(hostnameVerifier); - socket = new Socket(opts); + Socket.setDefaultSSLContext(createSSLContext()); + socket = new Socket(createOptions()); socket.on(Socket.EVENT_OPEN, new Emitter.Listener() { @Override public void call(Object... args) { From f4b2816cf0a5cf9f6c8b5df85e42e1381602d163 Mon Sep 17 00:00:00 2001 From: Yu-Hsuan Lin Date: Sat, 2 May 2015 01:31:52 +0800 Subject: [PATCH 6/7] Set HostnameVerifier as an Options --- .../github/nkzawa/engineio/client/Socket.java | 4 ++++ .../nkzawa/engineio/client/Transport.java | 4 ++++ .../engineio/client/transports/WebSocket.java | 3 +++ .../engineio/client/SSLConnectionTest.java | 21 ++++++++++--------- 4 files changed, 22 insertions(+), 10 deletions(-) diff --git a/src/main/java/com/github/nkzawa/engineio/client/Socket.java b/src/main/java/com/github/nkzawa/engineio/client/Socket.java index 4da61a6..73de492 100644 --- a/src/main/java/com/github/nkzawa/engineio/client/Socket.java +++ b/src/main/java/com/github/nkzawa/engineio/client/Socket.java @@ -10,6 +10,7 @@ import com.github.nkzawa.parseqs.ParseQS; import com.github.nkzawa.thread.EventThread; import org.json.JSONException; +import javax.net.ssl.HostnameVerifier; import javax.net.ssl.SSLContext; import java.net.URI; import java.net.URISyntaxException; @@ -121,6 +122,7 @@ public class Socket extends Emitter { private Future pingTimeoutTimer; private Future pingIntervalTimer; private SSLContext sslContext; + private HostnameVerifier hostnameVerifier; private ReadyState readyState; private ScheduledExecutorService heartbeatScheduler; @@ -197,6 +199,7 @@ public class Socket extends Emitter { opts.transports : new String[]{Polling.NAME, WebSocket.NAME})); this.policyPort = opts.policyPort != 0 ? opts.policyPort : 843; this.rememberUpgrade = opts.rememberUpgrade; + this.hostnameVerifier = opts.hostnameVerifier; } /** @@ -254,6 +257,7 @@ public class Socket extends Emitter { opts.timestampParam = this.timestampParam; opts.policyPort = this.policyPort; opts.socket = this; + opts.hostnameVerifier = this.hostnameVerifier; Transport transport; if (WebSocket.NAME.equals(name)) { diff --git a/src/main/java/com/github/nkzawa/engineio/client/Transport.java b/src/main/java/com/github/nkzawa/engineio/client/Transport.java index 8277075..2e12bad 100644 --- a/src/main/java/com/github/nkzawa/engineio/client/Transport.java +++ b/src/main/java/com/github/nkzawa/engineio/client/Transport.java @@ -6,6 +6,7 @@ import com.github.nkzawa.engineio.parser.Packet; import com.github.nkzawa.engineio.parser.Parser; import com.github.nkzawa.thread.EventThread; +import javax.net.ssl.HostnameVerifier; import javax.net.ssl.SSLContext; import java.util.Map; @@ -42,6 +43,7 @@ public abstract class Transport extends Emitter { protected String timestampParam; protected SSLContext sslContext; protected Socket socket; + protected HostnameVerifier hostnameVerifier; protected ReadyState readyState; @@ -55,6 +57,7 @@ public abstract class Transport extends Emitter { this.timestampRequests = opts.timestampRequests; this.sslContext = opts.sslContext; this.socket = opts.socket; + this.hostnameVerifier = opts.hostnameVerifier; } protected Transport onError(String msg, Exception desc) { @@ -144,6 +147,7 @@ public abstract class Transport extends Emitter { public int policyPort = -1; public Map query; public SSLContext sslContext; + public HostnameVerifier hostnameVerifier; protected Socket socket; } } diff --git a/src/main/java/com/github/nkzawa/engineio/client/transports/WebSocket.java b/src/main/java/com/github/nkzawa/engineio/client/transports/WebSocket.java index e33f975..a11439e 100644 --- a/src/main/java/com/github/nkzawa/engineio/client/transports/WebSocket.java +++ b/src/main/java/com/github/nkzawa/engineio/client/transports/WebSocket.java @@ -53,6 +53,9 @@ public class WebSocket extends Transport { SSLSocketFactory factory = sslContext.getSocketFactory();// (SSLSocketFactory) SSLSocketFactory.getDefault(); client.setSslSocketFactory(factory); } + if (this.hostnameVerifier != null) { + client.setHostnameVerifier(this.hostnameVerifier); + } Request.Builder builder = new Request.Builder().url(uri()); for (Map.Entry entry : headers.entrySet()) { builder.addHeader(entry.getKey(), entry.getValue()); diff --git a/src/test/java/com/github/nkzawa/engineio/client/SSLConnectionTest.java b/src/test/java/com/github/nkzawa/engineio/client/SSLConnectionTest.java index c4c0e5c..3ec7148 100644 --- a/src/test/java/com/github/nkzawa/engineio/client/SSLConnectionTest.java +++ b/src/test/java/com/github/nkzawa/engineio/client/SSLConnectionTest.java @@ -6,6 +6,7 @@ import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.JUnit4; +import javax.net.ssl.HostnameVerifier; import javax.net.ssl.KeyManagerFactory; import javax.net.ssl.SSLContext; import javax.net.ssl.TrustManagerFactory; @@ -23,15 +24,11 @@ import static org.junit.Assert.assertThat; @RunWith(JUnit4.class) public class SSLConnectionTest extends Connection { - static { - // for test on localhost - javax.net.ssl.HttpsURLConnection.setDefaultHostnameVerifier( - new javax.net.ssl.HostnameVerifier(){ - public boolean verify(String hostname, javax.net.ssl.SSLSession sslSession) { - return hostname.equals("localhost"); - } - }); - } + static HostnameVerifier hostnameVerifier = new javax.net.ssl.HostnameVerifier(){ + public boolean verify(String hostname, javax.net.ssl.SSLSession sslSession) { + return hostname.equals("localhost"); + } + }; private Socket socket; @@ -74,6 +71,7 @@ public class SSLConnectionTest extends Connection { Socket.Options opts = createOptions(); opts.sslContext = createSSLContext(); + opts.hostnameVerifier = SSLConnectionTest.hostnameVerifier; socket = new Socket(opts); socket.on(Socket.EVENT_OPEN, new Emitter.Listener() { @Override @@ -98,6 +96,7 @@ public class SSLConnectionTest extends Connection { Socket.Options opts = createOptions(); opts.sslContext = createSSLContext(); + opts.hostnameVerifier = SSLConnectionTest.hostnameVerifier; socket = new Socket(opts); socket.on(Socket.EVENT_OPEN, new Emitter.Listener() { @Override @@ -127,7 +126,9 @@ public class SSLConnectionTest extends Connection { final BlockingQueue values = new LinkedBlockingQueue(); Socket.setDefaultSSLContext(createSSLContext()); - socket = new Socket(createOptions()); + Socket.Options opts = createOptions(); + opts.hostnameVerifier = SSLConnectionTest.hostnameVerifier; + socket = new Socket(opts); socket.on(Socket.EVENT_OPEN, new Emitter.Listener() { @Override public void call(Object... args) { From a4babe599dd998fdf932ca8a6bf5f00dbd6720c0 Mon Sep 17 00:00:00 2001 From: Yu-Hsuan Lin Date: Sat, 2 May 2015 05:55:28 +0800 Subject: [PATCH 7/7] Set HostnameVerifier in PollingXHR --- .../engineio/client/transports/PollingXHR.java | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/github/nkzawa/engineio/client/transports/PollingXHR.java b/src/main/java/com/github/nkzawa/engineio/client/transports/PollingXHR.java index c937fc9..f82ef49 100644 --- a/src/main/java/com/github/nkzawa/engineio/client/transports/PollingXHR.java +++ b/src/main/java/com/github/nkzawa/engineio/client/transports/PollingXHR.java @@ -4,6 +4,7 @@ package com.github.nkzawa.engineio.client.transports; import com.github.nkzawa.emitter.Emitter; import com.github.nkzawa.thread.EventThread; +import javax.net.ssl.HostnameVerifier; import javax.net.ssl.HttpsURLConnection; import javax.net.ssl.SSLContext; import java.io.*; @@ -37,6 +38,7 @@ public class PollingXHR extends Polling { } opts.uri = this.uri(); opts.sslContext = this.sslContext; + opts.hostnameVerifier = this.hostnameVerifier; Request req = new Request(opts); @@ -148,12 +150,14 @@ public class PollingXHR extends Polling { private SSLContext sslContext; private HttpURLConnection xhr; + private HostnameVerifier hostnameVerifier; public Request(Options opts) { this.method = opts.method != null ? opts.method : "GET"; this.uri = opts.uri; this.data = opts.data; this.sslContext = opts.sslContext; + this.hostnameVerifier = opts.hostnameVerifier; } public void create() { @@ -170,8 +174,13 @@ public class PollingXHR extends Polling { xhr.setConnectTimeout(10000); - if (xhr instanceof HttpsURLConnection && this.sslContext != null) { - ((HttpsURLConnection)xhr).setSSLSocketFactory(this.sslContext.getSocketFactory()); + if (xhr instanceof HttpsURLConnection) { + if (this.sslContext != null) { + ((HttpsURLConnection)xhr).setSSLSocketFactory(this.sslContext.getSocketFactory()); + } + if (this.hostnameVerifier != null) { + ((HttpsURLConnection)xhr).setHostnameVerifier(this.hostnameVerifier); + } } Map headers = new TreeMap(String.CASE_INSENSITIVE_ORDER); @@ -317,6 +326,7 @@ public class PollingXHR extends Polling { public String method; public byte[] data; public SSLContext sslContext; + public HostnameVerifier hostnameVerifier; } } }