diff --git a/.classpath b/.classpath
index 002455a..18252f6 100644
--- a/.classpath
+++ b/.classpath
@@ -5,7 +5,10 @@
-
+
+
+
+
diff --git a/.gitignore b/.gitignore
index d1b29c6..8dfa31b 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,2 +1,4 @@
bin/
jar/
+.idea
+*.iml
diff --git a/README.markdown b/README.markdown
index 674bee0..43add8b 100644
--- a/README.markdown
+++ b/README.markdown
@@ -20,10 +20,24 @@ Features:
__Status:__ Connecting with Websocket is production ready. XHR is in beta.
+
## How to use
Using socket.io-java-client is quite simple. But lets see:
+Checkout and compile the project:
+
+``` bash
+git clone git://github.com/Gottox/socket.io-java-client.git
+cd socket.io-java-client
+ant jar
+mv jar/socketio.jar /path/to/your/libs/project
+```
+
+If you're using ant, change your build.xml to include socketio.jar. If you're eclipse, add the jar to your project buildpath.
+
+Afterwards, you'll be able to use this library:
+
``` java
SocketIO socket = new SocketIO("http://127.0.0.1:3001/");
diff --git a/build.xml b/build.xml
index 9c5a887..cd5186a 100644
--- a/build.xml
+++ b/build.xml
@@ -17,8 +17,11 @@
-
-
+
+
+
+
+
@@ -28,16 +31,6 @@
-
-
-
-
-
-
-
-
-
-
@@ -51,14 +44,6 @@
-
-
-
-
-
-
-
-
@@ -115,7 +100,7 @@
-
+
diff --git a/examples/logback.xml b/examples/logback.xml
new file mode 100644
index 0000000..a04713e
--- /dev/null
+++ b/examples/logback.xml
@@ -0,0 +1,16 @@
+
+
+
+
+
+ %d{HH:mm} %-5level %logger{36} - %msg%n
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/examples/perfomance/MessageReceiver.java b/examples/perfomance/MessageReceiver.java
new file mode 100644
index 0000000..f3dfbb3
--- /dev/null
+++ b/examples/perfomance/MessageReceiver.java
@@ -0,0 +1,85 @@
+package perfomance;
+
+import io.socket.*;
+import org.json.JSONException;
+
+import java.net.MalformedURLException;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * @author Keesun Baik
+ */
+public class MessageReceiver {
+
+ int connectionCount = 0;
+ int messageCount = 0;
+
+ public static void main(String[] args) throws MalformedURLException, JSONException, InterruptedException {
+ MessageReceiver client = new MessageReceiver();
+ List sockets = new ArrayList();
+
+ for(int i = 0 ; i < 10 ; i++) {
+ SocketIO socket = new SocketIO();
+ CallBack callback = new CallBack(socket, client);
+ socket.connect("http://10.96.250.207:19191/", callback);
+ sockets.add(socket);
+ System.out.printf("[%d] sockets tried to connect.\n", sockets.size());
+ if(i%100 == 0) {
+ Thread.sleep(500l);
+ }
+ }
+
+ while (true) {
+ Thread.sleep(1000l);
+ System.out.printf("[%d] connections, got [%d] messages.\n", client.getConnectionCount(), client.getMessageCount());
+ }
+ }
+
+ public int getConnectionCount() {
+ return connectionCount;
+ }
+
+ public int getMessageCount() {
+ return messageCount;
+ }
+
+ public static class CallBack extends DeafultIoCallback {
+
+ MessageReceiver client;
+
+ public CallBack(SocketIO socket, MessageReceiver sampleClient) {
+ super(socket);
+ this.client = sampleClient;
+ }
+
+ @Override
+ public void onConnect() {
+ this.client.plusConnectionCount();
+ }
+
+ @Override
+ public void on(String event, IOAcknowledge ack, Object... args) {
+ this.client.plusMessageCount();
+ }
+
+ @Override
+ public void onDisconnect() {
+ this.client.minusConnectionCount();
+ }
+
+ }
+
+ private synchronized void plusMessageCount() {
+ this.messageCount++;
+ }
+
+ private synchronized void minusConnectionCount() {
+ this.connectionCount--;
+ }
+
+ private synchronized void plusConnectionCount() {
+ this.connectionCount++;
+ }
+
+}
diff --git a/examples/perfomance/MessageSender.java b/examples/perfomance/MessageSender.java
new file mode 100644
index 0000000..267da92
--- /dev/null
+++ b/examples/perfomance/MessageSender.java
@@ -0,0 +1,28 @@
+package perfomance;
+
+import io.socket.DeafultIoCallback;
+import io.socket.SocketIO;
+import org.json.JSONException;
+import org.json.JSONObject;
+
+import java.net.MalformedURLException;
+
+/**
+ * @author Keesun Baik
+ */
+public class MessageSender {
+
+ public static void main(String[] args) throws MalformedURLException, JSONException, InterruptedException {
+ int sendingMessageCount = 0;
+ SocketIO socket = new SocketIO();
+ socket.connect("http://10.96.250.207:19191/", new DeafultIoCallback(socket));
+ while (true) {
+ JSONObject message = new JSONObject();
+ message.put("hello", "socket.io");
+ socket.emit("send", message);
+ sendingMessageCount++;
+ System.out.printf("sent [%d] messages\n", sendingMessageCount);
+ Thread.sleep(10000l);
+ }
+ }
+}
diff --git a/examples/perfomance/compileReceiver.sh b/examples/perfomance/compileReceiver.sh
new file mode 100644
index 0000000..4841192
--- /dev/null
+++ b/examples/perfomance/compileReceiver.sh
@@ -0,0 +1 @@
+javac -cp ~/apps/socket.io-java-client/jar/socketio.jar:~/apps/socket.io-java-client/libs/weberknecht-0.1.1.jar:~/apps/socket.io-java-client/libs/json-org.jar ./MessageReceiver.java
\ No newline at end of file
diff --git a/examples/perfomance/compileSender.sh b/examples/perfomance/compileSender.sh
new file mode 100644
index 0000000..547b8f4
--- /dev/null
+++ b/examples/perfomance/compileSender.sh
@@ -0,0 +1 @@
+javac -cp ~/apps/socket.io-java-client/jar/socketio.jar:~/apps/socket.io-java-client/libs/weberknecht-0.1.1.jar:~/apps/socket.io-java-client/libs/json-org.jar ./MessageSender.java
\ No newline at end of file
diff --git a/examples/perfomance/runReceiver.sh b/examples/perfomance/runReceiver.sh
new file mode 100644
index 0000000..3fb4e04
--- /dev/null
+++ b/examples/perfomance/runReceiver.sh
@@ -0,0 +1 @@
+java -Xms30G -Xmx30G -cp ~/apps/socket.io-java-client/jar/socketio.jar:~/apps/socket.io-java-client/libs/weberknecht-0.1.1.jar:~/apps/socket.io-java-client/libs/json-org.jar:. MessageReceiver
\ No newline at end of file
diff --git a/examples/perfomance/runSender.sh b/examples/perfomance/runSender.sh
new file mode 100644
index 0000000..d46332e
--- /dev/null
+++ b/examples/perfomance/runSender.sh
@@ -0,0 +1 @@
+java -Xms30G -Xmx30G -cp ~/apps/socket.io-java-client/jar/socketio.jar:~/apps/socket.io-java-client/libs/weberknecht-0.1.1.jar:~/apps/socket.io-java-client/libs/json-org.jar:. MessageSender
\ No newline at end of file
diff --git a/libs/WebSocket.jar b/libs/WebSocket.jar
new file mode 100644
index 0000000..ef36379
Binary files /dev/null and b/libs/WebSocket.jar differ
diff --git a/libs/logback-classic-1.0.6.jar b/libs/logback-classic-1.0.6.jar
new file mode 100644
index 0000000..140b334
Binary files /dev/null and b/libs/logback-classic-1.0.6.jar differ
diff --git a/libs/logback-core-1.0.6.jar b/libs/logback-core-1.0.6.jar
new file mode 100644
index 0000000..4522494
Binary files /dev/null and b/libs/logback-core-1.0.6.jar differ
diff --git a/libs/slf4j-api-1.6.6.jar b/libs/slf4j-api-1.6.6.jar
new file mode 100644
index 0000000..4c03fa6
Binary files /dev/null and b/libs/slf4j-api-1.6.6.jar differ
diff --git a/libs/weberknecht-0.1.1.jar b/libs/weberknecht-0.1.1.jar
deleted file mode 100644
index ad94960..0000000
Binary files a/libs/weberknecht-0.1.1.jar and /dev/null differ
diff --git a/src/io/socket/DeafultIoCallback.java b/src/io/socket/DeafultIoCallback.java
new file mode 100644
index 0000000..1648254
--- /dev/null
+++ b/src/io/socket/DeafultIoCallback.java
@@ -0,0 +1,43 @@
+package io.socket;
+
+import org.json.JSONObject;
+
+/**
+ * @author Keesun Baik
+ */
+public class DeafultIoCallback implements IOCallback {
+
+ protected SocketIO socket;
+
+ public DeafultIoCallback() {
+ }
+
+ public DeafultIoCallback(SocketIO socket) {
+ this.socket = socket;
+ }
+
+ @Override
+ public void onDisconnect() {
+ }
+
+ @Override
+ public void onConnect() {
+ }
+
+ @Override
+ public void onMessage(String data, IOAcknowledge ack) {
+ }
+
+ @Override
+ public void onMessage(JSONObject json, IOAcknowledge ack) {
+ }
+
+ @Override
+ public void on(String event, IOAcknowledge ack, Object... args) {
+ }
+
+ @Override
+ public void onError(SocketIOException socketIOException) {
+ }
+
+}
diff --git a/src/io/socket/IOConnection.java b/src/io/socket/IOConnection.java
index 403203d..e7dc52c 100644
--- a/src/io/socket/IOConnection.java
+++ b/src/io/socket/IOConnection.java
@@ -8,36 +8,32 @@
*/
package io.socket;
+import org.json.JSONArray;
+import org.json.JSONException;
+import org.json.JSONObject;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.net.ssl.HttpsURLConnection;
+import javax.net.ssl.SSLSocketFactory;
import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
-import java.util.Arrays;
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.LinkedList;
-import java.util.List;
+import java.util.*;
import java.util.Map.Entry;
-import java.util.Properties;
-import java.util.Scanner;
-import java.util.Timer;
-import java.util.TimerTask;
import java.util.concurrent.ConcurrentLinkedQueue;
-import java.util.logging.Logger;
import javax.net.ssl.HttpsURLConnection;
+import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocketFactory;
-import org.json.JSONArray;
-import org.json.JSONException;
-import org.json.JSONObject;
-
/**
* The Class IOConnection.
*/
class IOConnection implements IOCallback {
/** Debug logger */
- static final Logger logger = Logger.getLogger("io.socket");
+ static final Logger logger = LoggerFactory.getLogger(IOConnection.class);
public static final String FRAME_DELIMITER = "\ufffd";
@@ -66,8 +62,7 @@ class IOConnection implements IOCallback {
public static final String SOCKET_IO_1 = "/socket.io/1/";
/** The SSL socket factory for HTTPS connections */
- private static SSLSocketFactory sslSocketFactory = (SSLSocketFactory) SSLSocketFactory
- .getDefault();
+ private static SSLContext sslContext = null;
/** All available connections. */
private static HashMap> connections = new HashMap>();
@@ -148,7 +143,6 @@ private class HearbeatTimeoutTask extends TimerTask {
*/
@Override
public void run() {
- setState(STATE_INVALID);
error(new SocketIOException(
"Timeout Error. No heartbeat from server within life time of the socket. closing.",
lastException));
@@ -206,10 +200,19 @@ public void run() {
/**
* Set the socket factory used for SSL connections.
*
- * @param socketFactory
+ * @param sslContext
+ */
+ public static void setSslContext(SSLContext sslContext) {
+ IOConnection.sslContext = sslContext;
+ }
+
+ /**
+ * Get the socket factory used for SSL connections.
+ *
+ * @return socketFactory
*/
- public static void setDefaultSSLSocketFactory(SSLSocketFactory socketFactory) {
- sslSocketFactory = socketFactory;
+ public static SSLContext getSslContext() {
+ return sslContext;
}
/**
@@ -227,9 +230,11 @@ static public IOConnection register(String origin, SocketIO socket) {
list = new LinkedList();
connections.put(origin, list);
} else {
- for (IOConnection connection : list) {
- if (connection.register(socket))
- return connection;
+ synchronized (list) {
+ for (IOConnection connection : list) {
+ if (connection.register(socket))
+ return connection;
+ }
}
}
@@ -246,7 +251,7 @@ static public IOConnection register(String origin, SocketIO socket) {
* @return true, if successfully registered on this transport, otherwise
* false.
*/
- public boolean register(SocketIO socket) {
+ public synchronized boolean register(SocketIO socket) {
String namespace = socket.getNamespace();
if (sockets.containsKey(namespace))
return false;
@@ -265,7 +270,7 @@ public boolean register(SocketIO socket) {
* @param socket
* the socket to be shut down
*/
- public void unregister(SocketIO socket) {
+ public synchronized void unregister(SocketIO socket) {
sendPlain("0::" + socket.getNamespace());
sockets.remove(socket.getNamespace());
socket.getCallback().onDisconnect();
@@ -289,7 +294,7 @@ private void handshake() {
connection = url.openConnection();
if (connection instanceof HttpsURLConnection) {
((HttpsURLConnection) connection)
- .setSSLSocketFactory(sslSocketFactory);
+ .setSSLSocketFactory(sslContext.getSocketFactory());
}
connection.setConnectTimeout(connectTimeout);
connection.setReadTimeout(connectTimeout);
@@ -316,7 +321,7 @@ private void handshake() {
/**
* Connect transport.
*/
- private void connectTransport() {
+ private synchronized void connectTransport() {
if (getState() == STATE_INVALID)
return;
setState(STATE_CONNECTING);
@@ -409,19 +414,19 @@ private IOConnection(String url, SocketIO socket) {
/**
* Cleanup. IOConnection is not usable after this calling this.
*/
- private void cleanup() {
+ private synchronized void cleanup() {
setState(STATE_INVALID);
if (transport != null)
transport.disconnect();
sockets.clear();
synchronized (connections) {
List con = connections.get(urlStr);
- if (con.size() > 1)
+ if (con != null && con.size() > 1)
con.remove(this);
else
connections.remove(urlStr);
}
- logger.info("Cleanup");
+ logger.debug("Cleanup");
backgroundTimer.cancel();
}
@@ -444,19 +449,17 @@ private void error(SocketIOException e) {
* @param text
* the Text to be send.
*/
- private void sendPlain(String text) {
- synchronized (outputBuffer) {
- if (getState() == STATE_READY)
- try {
- logger.info("> " + text);
- transport.send(text);
- } catch (Exception e) {
- logger.info("IOEx: saving");
- outputBuffer.add(text);
- }
- else {
+ private synchronized void sendPlain(String text) {
+ if (getState() == STATE_READY)
+ try {
+ logger.debug("> " + text);
+ transport.send(text);
+ } catch (Exception e) {
+ logger.debug("IOEx: saving");
outputBuffer.add(text);
}
+ else {
+ outputBuffer.add(text);
}
}
@@ -472,13 +475,15 @@ private void invalidateTransport() {
/**
* Reset timeout.
*/
- private void resetTimeout() {
+ private synchronized void resetTimeout() {
if (heartbeatTimeoutTask != null) {
heartbeatTimeoutTask.cancel();
}
- heartbeatTimeoutTask = new HearbeatTimeoutTask();
- backgroundTimer.schedule(heartbeatTimeoutTask, closingTimeout
- + heartbeatTimeout);
+ if(getState() != STATE_INVALID) {
+ heartbeatTimeoutTask = new HearbeatTimeoutTask();
+ backgroundTimer.schedule(heartbeatTimeoutTask, closingTimeout
+ + heartbeatTimeout);
+ }
}
/**
@@ -506,38 +511,36 @@ private IOCallback findCallback(IOMessage message) throws SocketIOException {
*
* {@link IOTransport} calls this when a connection is established.
*/
- public void transportConnected() {
+ public synchronized void transportConnected() {
setState(STATE_READY);
if (reconnectTask != null) {
reconnectTask.cancel();
reconnectTask = null;
}
resetTimeout();
- synchronized (outputBuffer) {
- if (transport.canSendBulk()) {
- ConcurrentLinkedQueue outputBuffer = this.outputBuffer;
- this.outputBuffer = new ConcurrentLinkedQueue();
- try {
- // DEBUG
- String[] texts = outputBuffer
- .toArray(new String[outputBuffer.size()]);
- logger.info("Bulk start:");
- for (String text : texts) {
- logger.info("> " + text);
- }
- logger.info("Bulk end");
- // DEBUG END
- transport.sendBulk(texts);
- } catch (IOException e) {
- this.outputBuffer = outputBuffer;
+ if (transport.canSendBulk()) {
+ ConcurrentLinkedQueue outputBuffer = this.outputBuffer;
+ this.outputBuffer = new ConcurrentLinkedQueue();
+ try {
+ // DEBUG
+ String[] texts = outputBuffer.toArray(new String[outputBuffer
+ .size()]);
+ logger.debug("Bulk start:");
+ for (String text : texts) {
+ logger.debug("> {}", text);
}
- } else {
- String text;
- while ((text = outputBuffer.poll()) != null)
- sendPlain(text);
+ logger.debug("Bulk end");
+ // DEBUG END
+ transport.sendBulk(texts);
+ } catch (IOException e) {
+ this.outputBuffer = outputBuffer;
}
- this.keepAliveInQueue = false;
+ } else {
+ String text;
+ while ((text = outputBuffer.poll()) != null)
+ sendPlain(text);
}
+ this.keepAliveInQueue = false;
}
/**
@@ -602,7 +605,7 @@ public void transportData(String text) {
* the text
*/
public void transportMessage(String text) {
- logger.info("< " + text);
+ logger.debug("< {}", text);
IOMessage message;
try {
message = new IOMessage(text);
@@ -668,7 +671,7 @@ public void transportMessage(String text) {
+ "Message was: " + message.toString(), e));
}
} catch (JSONException e) {
- logger.warning("Malformated JSON received");
+ logger.warn("Malformated JSON received");
}
break;
case IOMessage.TYPE_EVENT:
@@ -694,7 +697,7 @@ public void transportMessage(String text) {
+ "Message was: " + message.toString(), e));
}
} catch (JSONException e) {
- logger.warning("Malformated JSON received");
+ logger.warn("Malformated JSON received");
}
break;
@@ -705,7 +708,7 @@ public void transportMessage(String text) {
int id = Integer.parseInt(data[0]);
IOAcknowledge ack = acknowledge.get(id);
if (ack == null)
- logger.warning("Received unknown ack packet");
+ logger.warn("Received unknown ack packet");
else {
JSONArray array = new JSONArray(data[1]);
Object[] args = new Object[array.length()];
@@ -715,9 +718,9 @@ public void transportMessage(String text) {
ack.ack(args);
}
} catch (NumberFormatException e) {
- logger.warning("Received malformated Acknowledge! This is potentially filling up the acknowledges!");
+ logger.warn("Received malformated Acknowledge! This is potentially filling up the acknowledges!");
} catch (JSONException e) {
- logger.warning("Received malformated Acknowledge data!");
+ logger.warn("Received malformated Acknowledge data!");
}
} else if (data.length == 1) {
sendPlain("6:::" + data[0]);
@@ -738,7 +741,7 @@ public void transportMessage(String text) {
case IOMessage.TYPE_NOOP:
break;
default:
- logger.warning("Unkown type received" + message.getType());
+ logger.warn("Unkown type received {}", message.getType());
break;
}
}
@@ -747,17 +750,15 @@ public void transportMessage(String text) {
* forces a reconnect. This had become useful on some android devices which
* do not shut down TCP-connections when switching from HSDPA to Wifi
*/
- public void reconnect() {
- synchronized (this) {
- if (getState() != STATE_INVALID) {
- invalidateTransport();
- setState(STATE_INTERRUPTED);
- if (reconnectTask != null) {
- reconnectTask.cancel();
- }
- reconnectTask = new ReconnectTask();
- backgroundTimer.schedule(reconnectTask, 1000);
+ public synchronized void reconnect() {
+ if (getState() != STATE_INVALID) {
+ invalidateTransport();
+ setState(STATE_INTERRUPTED);
+ if (reconnectTask != null) {
+ reconnectTask.cancel();
}
+ reconnectTask = new ReconnectTask();
+ backgroundTimer.schedule(reconnectTask, 1000);
}
}
@@ -873,7 +874,7 @@ public IOTransport getTransport() {
public void onDisconnect() {
SocketIO socket = sockets.get("");
if (socket != null)
- socket.getCallback().onConnect();
+ socket.getCallback().onDisconnect();
}
@Override
diff --git a/src/io/socket/SocketIO.java b/src/io/socket/SocketIO.java
index b3c7f42..7ecbaa3 100644
--- a/src/io/socket/SocketIO.java
+++ b/src/io/socket/SocketIO.java
@@ -8,10 +8,14 @@
*/
package io.socket;
+import org.json.JSONObject;
+
+import javax.net.ssl.SSLSocketFactory;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.Properties;
+import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocketFactory;
import org.json.JSONObject;
@@ -127,8 +131,8 @@ public SocketIO(final URL url) {
* Set the socket factory used for SSL connections.
* @param socketFactory
*/
- public static void setDefaultSSLSocketFactory(SSLSocketFactory socketFactory) {
- IOConnection.setDefaultSSLSocketFactory(socketFactory);
+ public static void setDefaultSSLSocketFactory(SSLContext sslContext) {
+ IOConnection.setSslContext(sslContext);
}
/**
@@ -198,6 +202,8 @@ else if (this.url == null)
* @return true if connecting has been initiated, false if not
*/
private boolean setAndConnect(URL url, IOCallback callback) {
+ if(this.connection != null)
+ throw new RuntimeException("You can connect your SocketIO instance only once. Use a fresh instance instead.");
if ((this.url != null && url != null)
|| (this.callback != null && callback != null))
return false;
diff --git a/src/io/socket/WebsocketTransport.java b/src/io/socket/WebsocketTransport.java
index 7ee667b..8eee840 100644
--- a/src/io/socket/WebsocketTransport.java
+++ b/src/io/socket/WebsocketTransport.java
@@ -1,144 +1,100 @@
-/*
- * socket.io-java-client WebsocketTransport.java
- *
- * Copyright (c) 2012, Enno Boland
- * socket.io-java-client is a implementation of the socket.io protocol in Java.
- *
- * See LICENSE file for more information
- */
package io.socket;
+import org.java_websocket.client.DefaultSSLWebSocketClientFactory;
+import org.java_websocket.client.WebSocketClient;
+import org.java_websocket.handshake.ServerHandshake;
+
+import javax.net.ssl.SSLContext;
import java.io.IOException;
import java.net.URI;
import java.net.URL;
import java.util.regex.Pattern;
-import de.roderick.weberknecht.WebSocketConnection;
-import de.roderick.weberknecht.WebSocketEventHandler;
-import de.roderick.weberknecht.WebSocketException;
-import de.roderick.weberknecht.WebSocketMessage;
-
-/**
- * The Class WebsocketTransport.
- */
-class WebsocketTransport implements IOTransport, WebSocketEventHandler {
-
- WebSocketConnection websocket;
-
- /** Pattern used to replace http:// by ws:// respectively https:// by wss:// */
- private final static Pattern PATTERN_HTTP = Pattern.compile("^http");
-
- /** The String to identify this Transport */
- public static final String TRANSPORT_NAME = "websocket";
-
- /** The IOConnection of this transport. */
- private IOConnection connection;
-
- /**
- * Creates a new Transport for the given url an {@link IOConnection}.
- *
- * @param url the url
- * @param connection the connection
- * @return the iO transport
- */
- public static IOTransport create(URL url, IOConnection connection) {
- URI uri = URI.create(
- PATTERN_HTTP.matcher(url.toString()).replaceFirst("ws")
- + IOConnection.SOCKET_IO_1 + TRANSPORT_NAME
- + "/" + connection.getSessionId());
-
- return new WebsocketTransport(uri, connection);
- }
-
- /**
- * Instantiates a new websocket transport.
- *
- * @param uri the uri
- * @param connection the connection
- * @throws WebSocketException
- */
- public WebsocketTransport(URI uri, IOConnection connection) {
- try {
- websocket = new WebSocketConnection(uri);
- } catch (WebSocketException e) {
- connection.transportError(e);
- return;
- }
- this.connection = connection;
- websocket.setEventHandler(this);
- }
-
- /* (non-Javadoc)
- * @see io.socket.IOTransport#disconnect()
- */
- @Override
- public void disconnect() {
- try {
- websocket.close();
- } catch (Exception e) {
- connection.transportError(e);
- }
- }
-
- /* (non-Javadoc)
- * @see io.socket.IOTransport#canSendBulk()
- */
- @Override
- public boolean canSendBulk() {
- return false;
- }
-
- /* (non-Javadoc)
- * @see io.socket.IOTransport#sendBulk(java.lang.String[])
- */
- @Override
- public void sendBulk(String[] texts) throws IOException {
- throw new RuntimeException("Cannot send Bulk!");
- }
-
- /* (non-Javadoc)
- * @see io.socket.IOTransport#invalidate()
- */
- @Override
- public void invalidate() {
- connection = null;
- }
-
- @Override
- public void onClose() {
- if(connection != null)
- connection.transportDisconnected();
- }
-
- @Override
- public void onMessage(WebSocketMessage arg0) {
- if(connection != null)
- connection.transportMessage(arg0.getText());
- }
-
- @Override
- public void onOpen() {
- if(connection != null)
- connection.transportConnected();
- }
-
- @Override
- public void connect() {
- try {
- websocket.connect();
- } catch (WebSocketException e) {
- connection.transportError(e);
- }
- }
-
- @Override
- public void send(String text) throws Exception {
- websocket.send(text);
- }
-
- @Override
- public String getName() {
- return TRANSPORT_NAME;
- }
-}
+class WebsocketTransport extends WebSocketClient implements IOTransport {
+ private final static Pattern PATTERN_HTTP = Pattern.compile("^http");
+ public static final String TRANSPORT_NAME = "websocket";
+ private IOConnection connection;
+ public static IOTransport create(URL url, IOConnection connection) {
+ URI uri = URI.create(
+ PATTERN_HTTP.matcher(url.toString()).replaceFirst("ws")
+ + IOConnection.SOCKET_IO_1 + TRANSPORT_NAME
+ + "/" + connection.getSessionId());
+
+ return new WebsocketTransport(uri, connection);
+ }
+
+ public WebsocketTransport(URI uri, IOConnection connection) {
+ super(uri);
+ this.connection = connection;
+ SSLContext context = IOConnection.getSslContext();
+ if("wss".equals(uri.getScheme()) && context != null) {
+ this.setWebSocketFactory(new DefaultSSLWebSocketClientFactory(context));
+ }
+ }
+
+ /* (non-Javadoc)
+ * @see io.socket.IOTransport#disconnect()
+ */
+ @Override
+ public void disconnect() {
+ try {
+ this.close();
+ } catch (Exception e) {
+ connection.transportError(e);
+ }
+ }
+
+ /* (non-Javadoc)
+ * @see io.socket.IOTransport#canSendBulk()
+ */
+ @Override
+ public boolean canSendBulk() {
+ return false;
+ }
+
+ /* (non-Javadoc)
+ * @see io.socket.IOTransport#sendBulk(java.lang.String[])
+ */
+ @Override
+ public void sendBulk(String[] texts) throws IOException {
+ throw new RuntimeException("Cannot send Bulk!");
+ }
+
+ /* (non-Javadoc)
+ * @see io.socket.IOTransport#invalidate()
+ */
+ @Override
+ public void invalidate() {
+ connection = null;
+ }
+
+ @Override
+ public void onClose(int code, String reason, boolean remote) {
+ if(connection != null)
+ connection.transportDisconnected();
+ }
+
+ @Override
+ public void onMessage(String text) {
+ if(connection != null)
+ connection.transportMessage(text);
+ }
+
+ @Override
+ public void onOpen(ServerHandshake handshakedata) {
+ if(connection != null)
+ connection.transportConnected();
+ }
+
+ @Override
+ public String getName() {
+ return TRANSPORT_NAME;
+ }
+
+ @Override
+ public void onError(Exception ex) {
+ // TODO Auto-generated method stub
+
+ }
+}
\ No newline at end of file
diff --git a/src/io/socket/XhrTransport.java b/src/io/socket/XhrTransport.java
index 94413e6..56f57fb 100644
--- a/src/io/socket/XhrTransport.java
+++ b/src/io/socket/XhrTransport.java
@@ -8,11 +8,7 @@
*/
package io.socket;
-import java.io.BufferedReader;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.InputStreamReader;
-import java.io.OutputStream;
+import java.io.*;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
@@ -20,6 +16,9 @@
import java.util.Iterator;
import java.util.concurrent.ConcurrentLinkedQueue;
+import javax.net.ssl.HttpsURLConnection;
+import javax.net.ssl.SSLContext;
+
/**
* The Class XhrTransport.
*/
@@ -76,6 +75,10 @@ public void run() {
URL url = new URL(XhrTransport.this.url.toString() + "?t="
+ System.currentTimeMillis());
urlConnection = (HttpURLConnection) url.openConnection();
+ SSLContext context = IOConnection.getSslContext();
+ if(urlConnection instanceof HttpsURLConnection && context != null) {
+ ((HttpsURLConnection)urlConnection).setSSLSocketFactory(context.getSocketFactory());
+ }
if (!queue.isEmpty()) {
urlConnection.setDoOutput(true);
OutputStream output = urlConnection.getOutputStream();
diff --git a/tests/io/socket/AbstractTestSocketIO.java b/tests/io/socket/AbstractTestSocketIO.java
index b52b110..8e1f6dd 100644
--- a/tests/io/socket/AbstractTestSocketIO.java
+++ b/tests/io/socket/AbstractTestSocketIO.java
@@ -36,7 +36,7 @@ public abstract class AbstractTestSocketIO implements IOCallback {
private static final String REQUEST_ACKNOWLEDGE = "requestAcknowledge";
/** The Constant to the node executable */
- private final static String NODE = "node";
+ private final static String NODE = "/usr/local/bin/node";
/** The port of this test, randomly choosed */
private int port = -1;
@@ -98,7 +98,7 @@ public void setUp() throws Exception {
node = Runtime.getRuntime().exec(
new String[] { NODE, "./tests/io/socket/testutils/socketio.js",
"" + getPort(), transport });
- proxy = new MutateProxy(getPort()+1, getPort());
+ proxy = new MutateProxy(getPort() + 1, getPort());
proxy.start();
stdoutThread = new Thread("stdoutThread") {
@@ -190,7 +190,8 @@ public void tearDown() throws Exception {
*/
void doConnect() throws Exception {
// Setting up socket connection
- socket = new SocketIO("http://127.0.0.1:" + getProxyPort() + "/main", this);
+ socket = new SocketIO("http://127.0.0.1:" + getProxyPort() + "/main",
+ this);
assertEquals("onConnect", takeEvent());
assertEquals(transport, socket.getTransport());
}
@@ -245,12 +246,12 @@ public void emitAndOn() throws Exception {
socket.emit("echo");
assertEquals("Test String", "on", takeEvent());
-
+
String str = "TESTSTRING";
socket.emit("echo", str);
assertEquals("Test String", "on", takeEvent());
assertEquals(str, takeArg());
-
+
JSONObject obj = new JSONObject("{'foo':'bar'}");
socket.emit("echo", obj);
assertEquals("Test JSON", "on", takeEvent());
@@ -291,16 +292,16 @@ public void emitAndMessage() throws Exception {
*/
@Test(timeout = TIMEOUT)
public void namespaces() throws Exception {
- SocketIO ns1 = new SocketIO("http://127.0.0.1:" + getProxyPort() + "/ns1",
- this);
+ SocketIO ns1 = new SocketIO("http://127.0.0.1:" + getProxyPort()
+ + "/ns1", this);
assertEquals("onConnect", takeEvent());
doConnect();
ns1.disconnect();
assertEquals("onDisconnect", takeEvent());
- SocketIO ns2 = new SocketIO("http://127.0.0.1:" + getProxyPort() + "/ns2",
- this);
+ SocketIO ns2 = new SocketIO("http://127.0.0.1:" + getProxyPort()
+ + "/ns2", this);
assertEquals("onConnect", takeEvent());
assertEquals("onMessage_string", takeEvent());
assertEquals("ns2", takeArg());
@@ -311,8 +312,8 @@ public void namespaces() throws Exception {
assertEquals("onMessage_string", takeEvent());
assertEquals("TESTSTRING", takeArg());
- SocketIO ns2_2 = new SocketIO("http://127.0.0.1:" + getProxyPort() + "/ns2",
- this);
+ SocketIO ns2_2 = new SocketIO("http://127.0.0.1:" + getProxyPort()
+ + "/ns2", this);
assertEquals("onConnect", takeEvent());
assertEquals("onMessage_string", takeEvent());
@@ -357,14 +358,34 @@ public void ack(Object... args) {
}, "TESTSTRING");
assertEquals("ack", takeEvent());
assertEquals("TESTSTRING", takeArg());
-
+
socket.emit(REQUEST_ACKNOWLEDGE, "TESTSTRING");
assertEquals("on", takeEvent());
- assertEquals("TESTSTRING", takeArg());
+ assertEquals("TESTSTRING", takeArg());
assertEquals("ACKNOWLEDGE:TESTSTRING", takeLine());
doClose();
}
+ @Test(timeout = TIMEOUT)
+ public void reconnectInvalidated() throws Exception {
+ doConnect();
+ socket.disconnect();
+ try {
+ socket.connect(this);
+ fail("reconnecting an invalidated socket should fail");
+ } catch (RuntimeException ex) {
+ }
+ }
+
+ @Test(timeout = TIMEOUT)
+ public void sendUtf8() throws Exception {
+ doConnect();
+ socket.emit("fooo", "\uD83C\uDF84");
+ socket.emit("fooo", "🎄");
+ assertEquals("on", takeEvent());
+ doClose();
+ }
+
// END TESTS
/**
@@ -470,7 +491,7 @@ public void onMessage(JSONObject json, IOAcknowledge ack) {
@Override
public void on(String event, IOAcknowledge ack, Object... args) {
events.add("on");
- if(event.equals(REQUEST_ACKNOWLEDGE)) {
+ if (event.equals(REQUEST_ACKNOWLEDGE)) {
ack.ack(args);
}
this.args.addAll(Arrays.asList(args));
@@ -497,9 +518,8 @@ public int getPort() {
port = 2048 + (int) (Math.random() * 10000) * 2;
return port;
}
-
+
public int getProxyPort() {
return getPort() + (proxy == null ? 0 : 1);
}
-
}