Options for inject okhttp Call/WebSocket factory
This commit is contained in:
13
README.md
13
README.md
@@ -94,14 +94,19 @@ socket.on(Socket.EVENT_OPEN, new Emitter.Listener() {
|
|||||||
Use custom SSL settings:
|
Use custom SSL settings:
|
||||||
|
|
||||||
```java
|
```java
|
||||||
|
OkHttpClient okHttpClient = new OkHttpClient.Builder()
|
||||||
|
.hostnameVerifier(myHostnameVerifier)
|
||||||
|
.sslSocketFactory(mySSLContext.getSocketFactory(), myX509TrustManager)
|
||||||
|
.build();
|
||||||
|
|
||||||
// default SSLContext for all sockets
|
// default SSLContext for all sockets
|
||||||
Socket.setDefaultSSLContext(mySSLContext);
|
Socket.setDefaultOkHttpWebSocketFactory(okHttpClient);
|
||||||
Socket.setDefaultHostnameVerifier(myHostnameVerifier);
|
Socket.setDefaultOkHttpCallFactory(okHttpClient);
|
||||||
|
|
||||||
// set as an option
|
// set as an option
|
||||||
opts = new Socket.Options();
|
opts = new Socket.Options();
|
||||||
opts.sslContext = mySSLContext;
|
opts.callFactory = okHttpClient;
|
||||||
opts.hostnameVerifier = myHostnameVerifier;
|
opts.webSocketFactory = okHttpClient;
|
||||||
socket = new Socket(opts);
|
socket = new Socket(opts);
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|||||||
2
pom.xml
2
pom.xml
@@ -49,7 +49,7 @@
|
|||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.squareup.okhttp3</groupId>
|
<groupId>com.squareup.okhttp3</groupId>
|
||||||
<artifactId>okhttp</artifactId>
|
<artifactId>okhttp</artifactId>
|
||||||
<version>3.5.0</version>
|
<version>3.7.0</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.json</groupId>
|
<groupId>org.json</groupId>
|
||||||
|
|||||||
@@ -1,5 +1,21 @@
|
|||||||
package io.socket.engineio.client;
|
package io.socket.engineio.client;
|
||||||
|
|
||||||
|
import org.json.JSONException;
|
||||||
|
|
||||||
|
import java.net.URI;
|
||||||
|
import java.net.URISyntaxException;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.LinkedList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.concurrent.Executors;
|
||||||
|
import java.util.concurrent.Future;
|
||||||
|
import java.util.concurrent.ScheduledExecutorService;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
import io.socket.emitter.Emitter;
|
import io.socket.emitter.Emitter;
|
||||||
import io.socket.engineio.client.transports.Polling;
|
import io.socket.engineio.client.transports.Polling;
|
||||||
import io.socket.engineio.client.transports.PollingXHR;
|
import io.socket.engineio.client.transports.PollingXHR;
|
||||||
@@ -8,19 +24,7 @@ import io.socket.engineio.parser.Packet;
|
|||||||
import io.socket.engineio.parser.Parser;
|
import io.socket.engineio.parser.Parser;
|
||||||
import io.socket.parseqs.ParseQS;
|
import io.socket.parseqs.ParseQS;
|
||||||
import io.socket.thread.EventThread;
|
import io.socket.thread.EventThread;
|
||||||
import org.json.JSONException;
|
import okhttp3.OkHttpClient;
|
||||||
|
|
||||||
import javax.net.ssl.HostnameVerifier;
|
|
||||||
import javax.net.ssl.SSLContext;
|
|
||||||
import java.net.Proxy;
|
|
||||||
import java.net.URI;
|
|
||||||
import java.net.URISyntaxException;
|
|
||||||
import java.util.*;
|
|
||||||
import java.util.concurrent.Executors;
|
|
||||||
import java.util.concurrent.Future;
|
|
||||||
import java.util.concurrent.ScheduledExecutorService;
|
|
||||||
import java.util.concurrent.TimeUnit;
|
|
||||||
import java.util.logging.Logger;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -98,8 +102,9 @@ public class Socket extends Emitter {
|
|||||||
|
|
||||||
private static boolean priorWebsocketSuccess = false;
|
private static boolean priorWebsocketSuccess = false;
|
||||||
|
|
||||||
private static SSLContext defaultSSLContext;
|
private static okhttp3.WebSocket.Factory defaultWebSocketFactory;
|
||||||
private static HostnameVerifier defaultHostnameVerifier;
|
private static okhttp3.Call.Factory defaultCallFactory;
|
||||||
|
private static OkHttpClient defaultOkHttpClient;
|
||||||
|
|
||||||
private boolean secure;
|
private boolean secure;
|
||||||
private boolean upgrade;
|
private boolean upgrade;
|
||||||
@@ -122,11 +127,8 @@ public class Socket extends Emitter {
|
|||||||
/*package*/ Transport transport;
|
/*package*/ Transport transport;
|
||||||
private Future pingTimeoutTimer;
|
private Future pingTimeoutTimer;
|
||||||
private Future pingIntervalTimer;
|
private Future pingIntervalTimer;
|
||||||
private SSLContext sslContext;
|
private okhttp3.WebSocket.Factory webSocketFactory;
|
||||||
private HostnameVerifier hostnameVerifier;
|
private okhttp3.Call.Factory callFactory;
|
||||||
public Proxy proxy;
|
|
||||||
public String proxyLogin;
|
|
||||||
public String proxyPassword;
|
|
||||||
|
|
||||||
private ReadyState readyState;
|
private ReadyState readyState;
|
||||||
private ScheduledExecutorService heartbeatScheduler;
|
private ScheduledExecutorService heartbeatScheduler;
|
||||||
@@ -190,7 +192,6 @@ public class Socket extends Emitter {
|
|||||||
opts.port = this.secure ? 443 : 80;
|
opts.port = this.secure ? 443 : 80;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.sslContext = opts.sslContext != null ? opts.sslContext : defaultSSLContext;
|
|
||||||
this.hostname = opts.hostname != null ? opts.hostname : "localhost";
|
this.hostname = opts.hostname != null ? opts.hostname : "localhost";
|
||||||
this.port = opts.port;
|
this.port = opts.port;
|
||||||
this.query = opts.query != null ?
|
this.query = opts.query != null ?
|
||||||
@@ -203,18 +204,28 @@ public class Socket extends Emitter {
|
|||||||
opts.transports : new String[]{Polling.NAME, WebSocket.NAME}));
|
opts.transports : new String[]{Polling.NAME, WebSocket.NAME}));
|
||||||
this.policyPort = opts.policyPort != 0 ? opts.policyPort : 843;
|
this.policyPort = opts.policyPort != 0 ? opts.policyPort : 843;
|
||||||
this.rememberUpgrade = opts.rememberUpgrade;
|
this.rememberUpgrade = opts.rememberUpgrade;
|
||||||
this.hostnameVerifier = opts.hostnameVerifier != null ? opts.hostnameVerifier : defaultHostnameVerifier;
|
this.callFactory = opts.callFactory != null ? opts.callFactory : defaultCallFactory;
|
||||||
this.proxy = opts.proxy;
|
this.webSocketFactory = opts.webSocketFactory != null ? opts.webSocketFactory : defaultWebSocketFactory;
|
||||||
this.proxyLogin = opts.proxyLogin;
|
if (callFactory == null) {
|
||||||
this.proxyPassword = opts.proxyPassword;
|
if (defaultOkHttpClient == null) {
|
||||||
|
defaultOkHttpClient = new OkHttpClient();
|
||||||
|
}
|
||||||
|
callFactory = defaultOkHttpClient;
|
||||||
|
}
|
||||||
|
if (webSocketFactory == null) {
|
||||||
|
if (defaultOkHttpClient == null) {
|
||||||
|
defaultOkHttpClient = new OkHttpClient();
|
||||||
|
}
|
||||||
|
webSocketFactory = defaultOkHttpClient;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void setDefaultSSLContext(SSLContext sslContext) {
|
public static void setDefaultOkHttpWebSocketFactory(okhttp3.WebSocket.Factory factory) {
|
||||||
defaultSSLContext = sslContext;
|
defaultWebSocketFactory = factory;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void setDefaultHostnameVerifier(HostnameVerifier hostnameVerifier) {
|
public static void setDefaultOkHttpCallFactory(okhttp3.Call.Factory factory) {
|
||||||
defaultHostnameVerifier = hostnameVerifier;
|
defaultCallFactory = factory;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -262,7 +273,6 @@ public class Socket extends Emitter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Transport.Options opts = new Transport.Options();
|
Transport.Options opts = new Transport.Options();
|
||||||
opts.sslContext = this.sslContext;
|
|
||||||
opts.hostname = this.hostname;
|
opts.hostname = this.hostname;
|
||||||
opts.port = this.port;
|
opts.port = this.port;
|
||||||
opts.secure = this.secure;
|
opts.secure = this.secure;
|
||||||
@@ -272,10 +282,8 @@ public class Socket extends Emitter {
|
|||||||
opts.timestampParam = this.timestampParam;
|
opts.timestampParam = this.timestampParam;
|
||||||
opts.policyPort = this.policyPort;
|
opts.policyPort = this.policyPort;
|
||||||
opts.socket = this;
|
opts.socket = this;
|
||||||
opts.hostnameVerifier = this.hostnameVerifier;
|
opts.callFactory = this.callFactory;
|
||||||
opts.proxy = this.proxy;
|
opts.webSocketFactory = this.webSocketFactory;
|
||||||
opts.proxyLogin = this.proxyLogin;
|
|
||||||
opts.proxyPassword = this.proxyPassword;
|
|
||||||
|
|
||||||
Transport transport;
|
Transport transport;
|
||||||
if (WebSocket.NAME.equals(name)) {
|
if (WebSocket.NAME.equals(name)) {
|
||||||
|
|||||||
@@ -1,16 +1,15 @@
|
|||||||
package io.socket.engineio.client;
|
package io.socket.engineio.client;
|
||||||
|
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
import io.socket.emitter.Emitter;
|
import io.socket.emitter.Emitter;
|
||||||
import io.socket.engineio.parser.Packet;
|
import io.socket.engineio.parser.Packet;
|
||||||
import io.socket.engineio.parser.Parser;
|
import io.socket.engineio.parser.Parser;
|
||||||
import io.socket.thread.EventThread;
|
import io.socket.thread.EventThread;
|
||||||
import io.socket.utf8.UTF8Exception;
|
import io.socket.utf8.UTF8Exception;
|
||||||
|
import okhttp3.Call;
|
||||||
import javax.net.ssl.HostnameVerifier;
|
import okhttp3.WebSocket;
|
||||||
import javax.net.ssl.SSLContext;
|
|
||||||
import java.net.Proxy;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
public abstract class Transport extends Emitter {
|
public abstract class Transport extends Emitter {
|
||||||
|
|
||||||
@@ -41,14 +40,10 @@ public abstract class Transport extends Emitter {
|
|||||||
protected String path;
|
protected String path;
|
||||||
protected String hostname;
|
protected String hostname;
|
||||||
protected String timestampParam;
|
protected String timestampParam;
|
||||||
protected SSLContext sslContext;
|
|
||||||
protected Socket socket;
|
protected Socket socket;
|
||||||
protected HostnameVerifier hostnameVerifier;
|
|
||||||
protected Proxy proxy;
|
|
||||||
protected String proxyLogin;
|
|
||||||
protected String proxyPassword;
|
|
||||||
|
|
||||||
protected ReadyState readyState;
|
protected ReadyState readyState;
|
||||||
|
protected WebSocket.Factory webSocketFactory;
|
||||||
|
protected Call.Factory callFactory;
|
||||||
|
|
||||||
public Transport(Options opts) {
|
public Transport(Options opts) {
|
||||||
this.path = opts.path;
|
this.path = opts.path;
|
||||||
@@ -58,12 +53,9 @@ public abstract class Transport extends Emitter {
|
|||||||
this.query = opts.query;
|
this.query = opts.query;
|
||||||
this.timestampParam = opts.timestampParam;
|
this.timestampParam = opts.timestampParam;
|
||||||
this.timestampRequests = opts.timestampRequests;
|
this.timestampRequests = opts.timestampRequests;
|
||||||
this.sslContext = opts.sslContext;
|
|
||||||
this.socket = opts.socket;
|
this.socket = opts.socket;
|
||||||
this.hostnameVerifier = opts.hostnameVerifier;
|
this.webSocketFactory = opts.webSocketFactory;
|
||||||
this.proxy = opts.proxy;
|
this.callFactory = opts.callFactory;
|
||||||
this.proxyLogin = opts.proxyLogin;
|
|
||||||
this.proxyPassword = opts.proxyPassword;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected Transport onError(String msg, Exception desc) {
|
protected Transport onError(String msg, Exception desc) {
|
||||||
@@ -156,11 +148,8 @@ public abstract class Transport extends Emitter {
|
|||||||
public int port = -1;
|
public int port = -1;
|
||||||
public int policyPort = -1;
|
public int policyPort = -1;
|
||||||
public Map<String, String> query;
|
public Map<String, String> query;
|
||||||
public SSLContext sslContext;
|
|
||||||
public HostnameVerifier hostnameVerifier;
|
|
||||||
protected Socket socket;
|
protected Socket socket;
|
||||||
public Proxy proxy;
|
public WebSocket.Factory webSocketFactory;
|
||||||
public String proxyLogin;
|
public Call.Factory callFactory;
|
||||||
public String proxyPassword;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,20 +1,25 @@
|
|||||||
package io.socket.engineio.client.transports;
|
package io.socket.engineio.client.transports;
|
||||||
|
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.LinkedList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.TreeMap;
|
||||||
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
import io.socket.emitter.Emitter;
|
import io.socket.emitter.Emitter;
|
||||||
import io.socket.engineio.client.Transport;
|
import io.socket.engineio.client.Transport;
|
||||||
import io.socket.thread.EventThread;
|
import io.socket.thread.EventThread;
|
||||||
|
import okhttp3.Call;
|
||||||
import javax.net.ssl.HostnameVerifier;
|
import okhttp3.Callback;
|
||||||
import javax.net.ssl.HttpsURLConnection;
|
import okhttp3.HttpUrl;
|
||||||
import javax.net.ssl.SSLContext;
|
import okhttp3.MediaType;
|
||||||
import java.io.*;
|
import okhttp3.OkHttpClient;
|
||||||
import java.net.HttpURLConnection;
|
import okhttp3.RequestBody;
|
||||||
import java.net.Proxy;
|
import okhttp3.Response;
|
||||||
import java.net.URL;
|
|
||||||
import java.nio.ByteBuffer;
|
|
||||||
import java.util.*;
|
|
||||||
import java.util.logging.Logger;
|
|
||||||
|
|
||||||
public class PollingXHR extends Polling {
|
public class PollingXHR extends Polling {
|
||||||
|
|
||||||
@@ -33,9 +38,7 @@ public class PollingXHR extends Polling {
|
|||||||
opts = new Request.Options();
|
opts = new Request.Options();
|
||||||
}
|
}
|
||||||
opts.uri = this.uri();
|
opts.uri = this.uri();
|
||||||
opts.sslContext = this.sslContext;
|
opts.callFactory = this.callFactory;
|
||||||
opts.hostnameVerifier = this.hostnameVerifier;
|
|
||||||
opts.proxy = this.proxy;
|
|
||||||
|
|
||||||
Request req = new Request(opts);
|
Request req = new Request(opts);
|
||||||
|
|
||||||
@@ -136,6 +139,7 @@ public class PollingXHR extends Polling {
|
|||||||
public static final String EVENT_ERROR = "error";
|
public static final String EVENT_ERROR = "error";
|
||||||
public static final String EVENT_REQUEST_HEADERS = "requestHeaders";
|
public static final String EVENT_REQUEST_HEADERS = "requestHeaders";
|
||||||
public static final String EVENT_RESPONSE_HEADERS = "responseHeaders";
|
public static final String EVENT_RESPONSE_HEADERS = "responseHeaders";
|
||||||
|
private static final String BINARY_CONTENT_TYPE = "application/octet-stream";
|
||||||
|
|
||||||
private String method;
|
private String method;
|
||||||
private String uri;
|
private String uri;
|
||||||
@@ -143,93 +147,60 @@ public class PollingXHR extends Polling {
|
|||||||
// data is always a binary
|
// data is always a binary
|
||||||
private byte[] data;
|
private byte[] data;
|
||||||
|
|
||||||
private SSLContext sslContext;
|
private Call.Factory callFactory;
|
||||||
private HttpURLConnection xhr;
|
private Response response;
|
||||||
private HostnameVerifier hostnameVerifier;
|
private Call requestCall;
|
||||||
private Proxy proxy;
|
|
||||||
|
|
||||||
public Request(Options opts) {
|
public Request(Options opts) {
|
||||||
this.method = opts.method != null ? opts.method : "GET";
|
this.method = opts.method != null ? opts.method : "GET";
|
||||||
this.uri = opts.uri;
|
this.uri = opts.uri;
|
||||||
this.data = opts.data;
|
this.data = opts.data;
|
||||||
this.sslContext = opts.sslContext;
|
this.callFactory = opts.callFactory != null ? opts.callFactory : new OkHttpClient();
|
||||||
this.hostnameVerifier = opts.hostnameVerifier;
|
|
||||||
this.proxy = opts.proxy;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void create() {
|
public void create() {
|
||||||
final Request self = this;
|
final Request self = this;
|
||||||
try {
|
|
||||||
logger.fine(String.format("xhr open %s: %s", this.method, this.uri));
|
logger.fine(String.format("xhr open %s: %s", this.method, this.uri));
|
||||||
URL url = new URL(this.uri);
|
|
||||||
xhr = proxy != null ? (HttpURLConnection) url.openConnection(proxy)
|
|
||||||
: (HttpURLConnection) url.openConnection();
|
|
||||||
xhr.setRequestMethod(this.method);
|
|
||||||
} catch (IOException e) {
|
|
||||||
this.onError(e);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
xhr.setConnectTimeout(10000);
|
|
||||||
|
|
||||||
if (xhr instanceof HttpsURLConnection) {
|
|
||||||
if (this.sslContext != null) {
|
|
||||||
((HttpsURLConnection)xhr).setSSLSocketFactory(this.sslContext.getSocketFactory());
|
|
||||||
}
|
|
||||||
if (this.hostnameVerifier != null) {
|
|
||||||
((HttpsURLConnection)xhr).setHostnameVerifier(this.hostnameVerifier);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Map<String, List<String>> headers = new TreeMap<String, List<String>>(String.CASE_INSENSITIVE_ORDER);
|
Map<String, List<String>> headers = new TreeMap<String, List<String>>(String.CASE_INSENSITIVE_ORDER);
|
||||||
|
|
||||||
if ("POST".equals(this.method)) {
|
if ("POST".equals(this.method)) {
|
||||||
xhr.setDoOutput(true);
|
headers.put("Content-type", new LinkedList<String>(Collections.singletonList(BINARY_CONTENT_TYPE)));
|
||||||
headers.put("Content-type", new LinkedList<String>(Arrays.asList("application/octet-stream")));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
self.onRequestHeaders(headers);
|
self.onRequestHeaders(headers);
|
||||||
|
|
||||||
|
logger.fine(String.format("sending xhr with url %s | data %s", this.uri, Arrays.toString(this.data)));
|
||||||
|
okhttp3.Request.Builder requestBuilder = new okhttp3.Request.Builder();
|
||||||
for (Map.Entry<String, List<String>> header : headers.entrySet()) {
|
for (Map.Entry<String, List<String>> header : headers.entrySet()) {
|
||||||
for (String v : header.getValue()){
|
for (String v : header.getValue()){
|
||||||
xhr.addRequestProperty(header.getKey(), v);
|
requestBuilder.addHeader(header.getKey(), v);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
okhttp3.Request request = requestBuilder
|
||||||
|
.url(HttpUrl.parse(self.uri))
|
||||||
|
.method(self.method, (self.data != null) ?
|
||||||
|
RequestBody.create(MediaType.parse(BINARY_CONTENT_TYPE), self.data) : null)
|
||||||
|
.build();
|
||||||
|
|
||||||
logger.fine(String.format("sending xhr with url %s | data %s", this.uri, this.data));
|
requestCall = callFactory.newCall(request);
|
||||||
new Thread(new Runnable() {
|
requestCall.enqueue(new Callback() {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void onFailure(Call call, IOException e) {
|
||||||
OutputStream output = null;
|
self.onError(e);
|
||||||
try {
|
|
||||||
if (self.data != null) {
|
|
||||||
xhr.setFixedLengthStreamingMode(self.data.length);
|
|
||||||
output = new BufferedOutputStream(xhr.getOutputStream());
|
|
||||||
output.write(self.data);
|
|
||||||
output.flush();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Map<String, List<String>> headers = xhr.getHeaderFields();
|
@Override
|
||||||
self.onResponseHeaders(headers);
|
public void onResponse(Call call, Response response) throws IOException {
|
||||||
|
self.response = response;
|
||||||
|
self.onResponseHeaders(response.headers().toMultimap());
|
||||||
|
|
||||||
final int statusCode = xhr.getResponseCode();
|
if (response.isSuccessful()) {
|
||||||
if (HttpURLConnection.HTTP_OK == statusCode) {
|
|
||||||
self.onLoad();
|
self.onLoad();
|
||||||
} else {
|
} else {
|
||||||
self.onError(new IOException(Integer.toString(statusCode)));
|
self.onError(new IOException(Integer.toString(response.code())));
|
||||||
}
|
|
||||||
} catch (IOException e) {
|
|
||||||
self.onError(e);
|
|
||||||
} catch (NullPointerException e) {
|
|
||||||
// It would occur to disconnect
|
|
||||||
// https://code.google.com/p/android/issues/detail?id=76592
|
|
||||||
self.onError(e);
|
|
||||||
} finally {
|
|
||||||
try {
|
|
||||||
if (output != null) output.close();
|
|
||||||
} catch (IOException e) {}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}).start();
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private void onSuccess() {
|
private void onSuccess() {
|
||||||
@@ -258,56 +229,17 @@ public class PollingXHR extends Polling {
|
|||||||
this.emit(EVENT_RESPONSE_HEADERS, headers);
|
this.emit(EVENT_RESPONSE_HEADERS, headers);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void cleanup() {
|
|
||||||
if (xhr == null) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
xhr.disconnect();
|
|
||||||
xhr = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void onLoad() {
|
private void onLoad() {
|
||||||
InputStream input = null;
|
String contentType = response.body().contentType().toString();
|
||||||
BufferedReader reader = null;
|
|
||||||
String contentType = xhr.getContentType();
|
|
||||||
try {
|
try {
|
||||||
if ("application/octet-stream".equalsIgnoreCase(contentType)) {
|
if (BINARY_CONTENT_TYPE.equalsIgnoreCase(contentType)) {
|
||||||
input = new BufferedInputStream(this.xhr.getInputStream());
|
this.onData(response.body().bytes());
|
||||||
List<byte[]> buffers = new ArrayList<byte[]>();
|
|
||||||
int capacity = 0;
|
|
||||||
int len = 0;
|
|
||||||
byte[] buffer = new byte[1024];
|
|
||||||
while ((len = input.read(buffer)) > 0) {
|
|
||||||
byte[] tempBuffer = new byte[len];
|
|
||||||
System.arraycopy(buffer, 0, tempBuffer, 0, len);
|
|
||||||
buffers.add(tempBuffer);
|
|
||||||
capacity += len;
|
|
||||||
}
|
|
||||||
ByteBuffer data = ByteBuffer.allocate(capacity);
|
|
||||||
for (byte[] b : buffers) {
|
|
||||||
data.put(b);
|
|
||||||
}
|
|
||||||
this.onData(data.array());
|
|
||||||
} else {
|
} else {
|
||||||
String line;
|
this.onData(response.body().string());
|
||||||
StringBuilder data = new StringBuilder();
|
|
||||||
reader = new BufferedReader(new InputStreamReader(xhr.getInputStream()));
|
|
||||||
while ((line = reader.readLine()) != null) {
|
|
||||||
data.append(line);
|
|
||||||
}
|
|
||||||
this.onData(data.toString());
|
|
||||||
}
|
}
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
this.onError(e);
|
this.onError(e);
|
||||||
} finally {
|
|
||||||
try {
|
|
||||||
if (input != null) input.close();
|
|
||||||
} catch (IOException e) {}
|
|
||||||
try {
|
|
||||||
if (reader != null) reader.close();
|
|
||||||
} catch (IOException e) {}
|
|
||||||
this.cleanup();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -316,9 +248,7 @@ public class PollingXHR extends Polling {
|
|||||||
public String uri;
|
public String uri;
|
||||||
public String method;
|
public String method;
|
||||||
public byte[] data;
|
public byte[] data;
|
||||||
public SSLContext sslContext;
|
public Call.Factory callFactory;
|
||||||
public HostnameVerifier hostnameVerifier;
|
|
||||||
public Proxy proxy;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,12 @@
|
|||||||
package io.socket.engineio.client.transports;
|
package io.socket.engineio.client.transports;
|
||||||
|
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.TreeMap;
|
||||||
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
import io.socket.engineio.client.Transport;
|
import io.socket.engineio.client.Transport;
|
||||||
import io.socket.engineio.parser.Packet;
|
import io.socket.engineio.parser.Packet;
|
||||||
import io.socket.engineio.parser.Parser;
|
import io.socket.engineio.parser.Parser;
|
||||||
@@ -8,18 +14,12 @@ import io.socket.parseqs.ParseQS;
|
|||||||
import io.socket.thread.EventThread;
|
import io.socket.thread.EventThread;
|
||||||
import io.socket.utf8.UTF8Exception;
|
import io.socket.utf8.UTF8Exception;
|
||||||
import io.socket.yeast.Yeast;
|
import io.socket.yeast.Yeast;
|
||||||
import okhttp3.*;
|
import okhttp3.OkHttpClient;
|
||||||
|
import okhttp3.Request;
|
||||||
|
import okhttp3.Response;
|
||||||
|
import okhttp3.WebSocketListener;
|
||||||
import okio.ByteString;
|
import okio.ByteString;
|
||||||
|
|
||||||
import javax.net.ssl.SSLSocketFactory;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.TreeMap;
|
|
||||||
import java.util.concurrent.TimeUnit;
|
|
||||||
import java.util.logging.Logger;
|
|
||||||
|
|
||||||
|
|
||||||
public class WebSocket extends Transport {
|
public class WebSocket extends Transport {
|
||||||
|
|
||||||
@@ -39,34 +39,7 @@ public class WebSocket extends Transport {
|
|||||||
this.emit(EVENT_REQUEST_HEADERS, headers);
|
this.emit(EVENT_REQUEST_HEADERS, headers);
|
||||||
|
|
||||||
final WebSocket self = this;
|
final WebSocket self = this;
|
||||||
OkHttpClient.Builder clientBuilder = new OkHttpClient.Builder()
|
okhttp3.WebSocket.Factory factory = webSocketFactory != null ? webSocketFactory : new OkHttpClient();
|
||||||
// turn off timeouts (github.com/socketio/engine.io-client-java/issues/32)
|
|
||||||
.connectTimeout(0, TimeUnit.MILLISECONDS)
|
|
||||||
.readTimeout(0, TimeUnit.MILLISECONDS)
|
|
||||||
.writeTimeout(0, TimeUnit.MILLISECONDS);
|
|
||||||
|
|
||||||
if (this.sslContext != null) {
|
|
||||||
SSLSocketFactory factory = sslContext.getSocketFactory();// (SSLSocketFactory) SSLSocketFactory.getDefault();
|
|
||||||
clientBuilder.sslSocketFactory(factory);
|
|
||||||
}
|
|
||||||
if (this.hostnameVerifier != null) {
|
|
||||||
clientBuilder.hostnameVerifier(this.hostnameVerifier);
|
|
||||||
}
|
|
||||||
if (proxy != null) {
|
|
||||||
clientBuilder.proxy(proxy);
|
|
||||||
}
|
|
||||||
if (proxyLogin != null && !proxyLogin.isEmpty()) {
|
|
||||||
final String credentials = Credentials.basic(proxyLogin, proxyPassword);
|
|
||||||
|
|
||||||
clientBuilder.proxyAuthenticator(new Authenticator() {
|
|
||||||
@Override
|
|
||||||
public Request authenticate(Route route, Response response) throws IOException {
|
|
||||||
return response.request().newBuilder()
|
|
||||||
.header("Proxy-Authorization", credentials)
|
|
||||||
.build();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
Request.Builder builder = new Request.Builder().url(uri());
|
Request.Builder builder = new Request.Builder().url(uri());
|
||||||
for (Map.Entry<String, List<String>> entry : headers.entrySet()) {
|
for (Map.Entry<String, List<String>> entry : headers.entrySet()) {
|
||||||
for (String v : entry.getValue()) {
|
for (String v : entry.getValue()) {
|
||||||
@@ -74,8 +47,7 @@ public class WebSocket extends Transport {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
final Request request = builder.build();
|
final Request request = builder.build();
|
||||||
final OkHttpClient client = clientBuilder.build();
|
ws = factory.newWebSocket(request, new WebSocketListener() {
|
||||||
ws = client.newWebSocket(request, new WebSocketListener() {
|
|
||||||
@Override
|
@Override
|
||||||
public void onOpen(okhttp3.WebSocket webSocket, Response response) {
|
public void onOpen(okhttp3.WebSocket webSocket, Response response) {
|
||||||
final Map<String, List<String>> headers = response.headers().toMultimap();
|
final Map<String, List<String>> headers = response.headers().toMultimap();
|
||||||
@@ -137,7 +109,6 @@ public class WebSocket extends Transport {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
client.dispatcher().executorService().shutdown();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void write(Packet[] packets) throws UTF8Exception {
|
protected void write(Packet[] packets) throws UTF8Exception {
|
||||||
@@ -187,14 +158,8 @@ public class WebSocket extends Transport {
|
|||||||
|
|
||||||
protected void doClose() {
|
protected void doClose() {
|
||||||
if (ws != null) {
|
if (ws != null) {
|
||||||
try {
|
|
||||||
ws.close(1000, "");
|
ws.close(1000, "");
|
||||||
} catch (IllegalStateException e) {
|
ws = null;
|
||||||
// websocket already closed
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (ws != null) {
|
|
||||||
ws.cancel();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ public class ExecutionTest extends Connection {
|
|||||||
|
|
||||||
private static final Logger logger = Logger.getLogger(Socket.class.getName());
|
private static final Logger logger = Logger.getLogger(Socket.class.getName());
|
||||||
|
|
||||||
final static int TIMEOUT = 30 * 1000;
|
final static int TIMEOUT = 100 * 1000;
|
||||||
|
|
||||||
@Test(timeout = TIMEOUT)
|
@Test(timeout = TIMEOUT)
|
||||||
public void execConnection() throws InterruptedException, IOException {
|
public void execConnection() throws InterruptedException, IOException {
|
||||||
|
|||||||
@@ -1,15 +1,10 @@
|
|||||||
package io.socket.engineio.client;
|
package io.socket.engineio.client;
|
||||||
|
|
||||||
import io.socket.emitter.Emitter;
|
|
||||||
import org.junit.After;
|
import org.junit.After;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.junit.runner.RunWith;
|
import org.junit.runner.RunWith;
|
||||||
import org.junit.runners.JUnit4;
|
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;
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.FileInputStream;
|
import java.io.FileInputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
@@ -18,23 +13,63 @@ import java.security.KeyStore;
|
|||||||
import java.util.concurrent.BlockingQueue;
|
import java.util.concurrent.BlockingQueue;
|
||||||
import java.util.concurrent.LinkedBlockingQueue;
|
import java.util.concurrent.LinkedBlockingQueue;
|
||||||
|
|
||||||
|
import javax.net.ssl.KeyManagerFactory;
|
||||||
|
import javax.net.ssl.SSLContext;
|
||||||
|
import javax.net.ssl.TrustManagerFactory;
|
||||||
|
import javax.net.ssl.X509TrustManager;
|
||||||
|
|
||||||
|
import io.socket.emitter.Emitter;
|
||||||
|
import okhttp3.OkHttpClient;
|
||||||
|
|
||||||
import static org.hamcrest.CoreMatchers.is;
|
import static org.hamcrest.CoreMatchers.is;
|
||||||
import static org.junit.Assert.assertThat;
|
import static org.junit.Assert.assertThat;
|
||||||
|
|
||||||
@RunWith(JUnit4.class)
|
@RunWith(JUnit4.class)
|
||||||
public class SSLConnectionTest extends Connection {
|
public class SSLConnectionTest extends Connection {
|
||||||
|
|
||||||
static HostnameVerifier hostnameVerifier = new javax.net.ssl.HostnameVerifier(){
|
private static OkHttpClient sOkHttpClient;
|
||||||
public boolean verify(String hostname, javax.net.ssl.SSLSession sslSession) {
|
|
||||||
return hostname.equals("localhost");
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
private Socket socket;
|
private Socket socket;
|
||||||
|
|
||||||
|
static {
|
||||||
|
try {
|
||||||
|
prepareOkHttpClient();
|
||||||
|
} catch (GeneralSecurityException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void prepareOkHttpClient() 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("TLSv1");
|
||||||
|
sslContext.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null);
|
||||||
|
|
||||||
|
sOkHttpClient = new OkHttpClient.Builder()
|
||||||
|
.hostnameVerifier(new javax.net.ssl.HostnameVerifier(){
|
||||||
|
public boolean verify(String hostname, javax.net.ssl.SSLSession sslSession) {
|
||||||
|
return hostname.equals("localhost");
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.sslSocketFactory(sslContext.getSocketFactory(),
|
||||||
|
(X509TrustManager) tmf.getTrustManagers()[0])
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
|
||||||
@After
|
@After
|
||||||
public void tearDown() {
|
public void tearDown() {
|
||||||
Socket.setDefaultSSLContext(null);
|
Socket.setDefaultOkHttpCallFactory(null);
|
||||||
|
Socket.setDefaultOkHttpWebSocketFactory(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -49,29 +84,13 @@ public class SSLConnectionTest extends Connection {
|
|||||||
return new String[] {"DEBUG=engine*", "PORT=" + PORT, "SSL=1"};
|
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("TLSv1");
|
|
||||||
sslContext.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null);
|
|
||||||
return sslContext;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test(timeout = TIMEOUT)
|
@Test(timeout = TIMEOUT)
|
||||||
public void connect() throws Exception {
|
public void connect() throws Exception {
|
||||||
final BlockingQueue<Object> values = new LinkedBlockingQueue<Object>();
|
final BlockingQueue<Object> values = new LinkedBlockingQueue<Object>();
|
||||||
|
|
||||||
Socket.Options opts = createOptions();
|
Socket.Options opts = createOptions();
|
||||||
opts.sslContext = createSSLContext();
|
opts.callFactory = sOkHttpClient;
|
||||||
opts.hostnameVerifier = SSLConnectionTest.hostnameVerifier;
|
opts.webSocketFactory = sOkHttpClient;
|
||||||
socket = new Socket(opts);
|
socket = new Socket(opts);
|
||||||
socket.on(Socket.EVENT_OPEN, new Emitter.Listener() {
|
socket.on(Socket.EVENT_OPEN, new Emitter.Listener() {
|
||||||
@Override
|
@Override
|
||||||
@@ -95,8 +114,8 @@ public class SSLConnectionTest extends Connection {
|
|||||||
final BlockingQueue<Object> values = new LinkedBlockingQueue<Object>();
|
final BlockingQueue<Object> values = new LinkedBlockingQueue<Object>();
|
||||||
|
|
||||||
Socket.Options opts = createOptions();
|
Socket.Options opts = createOptions();
|
||||||
opts.sslContext = createSSLContext();
|
opts.callFactory = sOkHttpClient;
|
||||||
opts.hostnameVerifier = SSLConnectionTest.hostnameVerifier;
|
opts.webSocketFactory = sOkHttpClient;
|
||||||
socket = new Socket(opts);
|
socket = new Socket(opts);
|
||||||
socket.on(Socket.EVENT_OPEN, new Emitter.Listener() {
|
socket.on(Socket.EVENT_OPEN, new Emitter.Listener() {
|
||||||
@Override
|
@Override
|
||||||
@@ -125,8 +144,8 @@ public class SSLConnectionTest extends Connection {
|
|||||||
public void defaultSSLContext() throws Exception {
|
public void defaultSSLContext() throws Exception {
|
||||||
final BlockingQueue<Object> values = new LinkedBlockingQueue<Object>();
|
final BlockingQueue<Object> values = new LinkedBlockingQueue<Object>();
|
||||||
|
|
||||||
Socket.setDefaultSSLContext(createSSLContext());
|
Socket.setDefaultOkHttpWebSocketFactory(sOkHttpClient);
|
||||||
Socket.setDefaultHostnameVerifier(SSLConnectionTest.hostnameVerifier);
|
Socket.setDefaultOkHttpCallFactory(sOkHttpClient);
|
||||||
socket = new Socket(createOptions());
|
socket = new Socket(createOptions());
|
||||||
socket.on(Socket.EVENT_OPEN, new Emitter.Listener() {
|
socket.on(Socket.EVENT_OPEN, new Emitter.Listener() {
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -163,8 +163,8 @@ public class ServerConnectionTest extends Connection {
|
|||||||
});
|
});
|
||||||
socket.open();
|
socket.open();
|
||||||
|
|
||||||
assertThat(messages.take(), is("foo"));
|
|
||||||
assertThat(messages.take(), is("hi"));
|
assertThat(messages.take(), is("hi"));
|
||||||
|
assertThat(messages.take(), is("foo"));
|
||||||
socket.close();
|
socket.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user