diff --git a/examples/chat-client/src/org/socketio/chat/Chat.java b/examples/chat-client/src/org/socketio/chat/Chat.java
new file mode 100644
index 0000000..ff0942c
--- /dev/null
+++ b/examples/chat-client/src/org/socketio/chat/Chat.java
@@ -0,0 +1,43 @@
+package org.socketio.chat;
+
+import com.clwillingham.socket.io.IOSocket;
+import java.io.IOException;
+import org.json.JSONException;
+import org.json.JSONObject;
+
+public class Chat extends Thread {
+ private IOSocket socket;
+ private ChatCallback callback;
+
+ public Chat(ChatCallbackAdapter callback) {
+ this.callback = new ChatCallback(callback);
+ }
+
+ @Override
+ public void run() {
+ socket = new IOSocket("http://localhost:3000", callback);
+ socket.connect();
+ }
+
+ public void sendMessage(String message) {
+ try {
+ JSONObject json = new JSONObject();
+ json.putOpt("message", message);
+ socket.emit("user message", json);
+ } catch (IOException ex) {
+ ex.printStackTrace();
+ } catch (JSONException ex) {
+ ex.printStackTrace();
+ }
+ }
+
+ public void join(String nickname) {
+ try {
+ JSONObject json = new JSONObject();
+ json.putOpt("nickname", nickname);
+ socket.emit("nickname", json, callback);
+ } catch (Exception ex) {
+ ex.printStackTrace();
+ }
+ }
+}
diff --git a/examples/chat-client/src/org/socketio/chat/ChatCallback.java b/examples/chat-client/src/org/socketio/chat/ChatCallback.java
new file mode 100644
index 0000000..0887786
--- /dev/null
+++ b/examples/chat-client/src/org/socketio/chat/ChatCallback.java
@@ -0,0 +1,51 @@
+package org.socketio.chat;
+
+import com.clwillingham.socket.io.AckCallback;
+import com.clwillingham.socket.io.MessageCallback;
+import org.json.JSONArray;
+import org.json.JSONException;
+import org.json.JSONObject;
+
+public class ChatCallback extends AckCallback implements MessageCallback {
+ private ChatCallbackAdapter callback;
+
+ public ChatCallback(ChatCallbackAdapter callback) {
+ this.callback = callback;
+ }
+
+ @Override
+ public void callback(JSONArray data) throws JSONException {
+ callback.callback(data);
+ }
+
+ @Override
+ public void on(String event, JSONObject... data) {
+ callback.on(event, data);
+ }
+
+ @Override
+ public void onMessage(String message) {
+ callback.onMessage(message);
+ }
+
+ @Override
+ public void onMessage(JSONObject json) {
+ callback.onMessage(json);
+ }
+
+ @Override
+ public void onConnect() {
+ callback.onConnect();
+ }
+
+ @Override
+ public void onDisconnect() {
+ callback.onDisconnect();
+ }
+
+ @Override
+ public void onConnectFailure() {
+ callback.onConnectFailure();
+ }
+
+}
diff --git a/examples/chat-client/src/org/socketio/chat/ChatCallbackAdapter.java b/examples/chat-client/src/org/socketio/chat/ChatCallbackAdapter.java
new file mode 100644
index 0000000..bd9287a
--- /dev/null
+++ b/examples/chat-client/src/org/socketio/chat/ChatCallbackAdapter.java
@@ -0,0 +1,15 @@
+package org.socketio.chat;
+
+import org.json.JSONArray;
+import org.json.JSONException;
+import org.json.JSONObject;
+
+public interface ChatCallbackAdapter {
+ public void callback(JSONArray data) throws JSONException;
+ public void on(String event, JSONObject... data);
+ public void onMessage(String message);
+ public void onMessage(JSONObject json);
+ public void onConnect();
+ public void onDisconnect();
+ public void onConnectFailure();
+}
diff --git a/examples/chat-client/src/org/socketio/chat/ChatFrame.form b/examples/chat-client/src/org/socketio/chat/ChatFrame.form
new file mode 100644
index 0000000..9aaf619
--- /dev/null
+++ b/examples/chat-client/src/org/socketio/chat/ChatFrame.form
@@ -0,0 +1,107 @@
+
+
+
diff --git a/examples/chat-client/src/org/socketio/chat/ChatFrame.java b/examples/chat-client/src/org/socketio/chat/ChatFrame.java
new file mode 100644
index 0000000..afa3203
--- /dev/null
+++ b/examples/chat-client/src/org/socketio/chat/ChatFrame.java
@@ -0,0 +1,200 @@
+package org.socketio.chat;
+
+import javax.swing.JOptionPane;
+import org.json.JSONArray;
+import org.json.JSONException;
+import org.json.JSONObject;
+
+public class ChatFrame extends javax.swing.JFrame implements ChatCallbackAdapter {
+ private Chat chat;
+
+ /** Creates new form Chat */
+ public ChatFrame() {
+ initComponents();
+ setVisible(true);
+ setLocationRelativeTo(null);
+ disableNewMessages();
+
+ startChat();
+ }
+
+ /** This method is called from within the constructor to
+ * initialize the form.
+ * WARNING: Do NOT modify this code. The content of this method is
+ * always regenerated by the Form Editor.
+ */
+ @SuppressWarnings("unchecked")
+ // //GEN-BEGIN:initComponents
+ private void initComponents() {
+
+ MessagesScrollPane = new javax.swing.JScrollPane();
+ MessagesTextArea = new javax.swing.JTextArea();
+ NewMessageScrollPane = new javax.swing.JScrollPane();
+ NewMessageTextArea = new javax.swing.JTextArea();
+ SendButton = new javax.swing.JButton();
+ OnlineUsersLabel = new javax.swing.JLabel();
+ OnlineUsers = new javax.swing.JLabel();
+
+ setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
+ setTitle("Chat");
+
+ MessagesTextArea.setColumns(20);
+ MessagesTextArea.setEditable(false);
+ MessagesTextArea.setRows(5);
+ MessagesScrollPane.setViewportView(MessagesTextArea);
+
+ NewMessageTextArea.setColumns(20);
+ NewMessageTextArea.setRows(5);
+ NewMessageScrollPane.setViewportView(NewMessageTextArea);
+
+ SendButton.setText("Send");
+ SendButton.addActionListener(new java.awt.event.ActionListener() {
+ public void actionPerformed(java.awt.event.ActionEvent evt) {
+ SendButtonActionPerformed(evt);
+ }
+ });
+
+ OnlineUsersLabel.setText("Online:");
+
+ javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
+ getContentPane().setLayout(layout);
+ layout.setHorizontalGroup(
+ layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
+ .addContainerGap()
+ .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
+ .addComponent(MessagesScrollPane, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, 376, Short.MAX_VALUE)
+ .addGroup(layout.createSequentialGroup()
+ .addComponent(NewMessageScrollPane, javax.swing.GroupLayout.PREFERRED_SIZE, 295, javax.swing.GroupLayout.PREFERRED_SIZE)
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+ .addComponent(SendButton, javax.swing.GroupLayout.DEFAULT_SIZE, 75, Short.MAX_VALUE))
+ .addGroup(javax.swing.GroupLayout.Alignment.LEADING, layout.createSequentialGroup()
+ .addComponent(OnlineUsersLabel)
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+ .addComponent(OnlineUsers, javax.swing.GroupLayout.DEFAULT_SIZE, 326, Short.MAX_VALUE)))
+ .addContainerGap())
+ );
+ layout.setVerticalGroup(
+ layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
+ .addContainerGap()
+ .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
+ .addComponent(OnlineUsersLabel)
+ .addComponent(OnlineUsers))
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
+ .addComponent(MessagesScrollPane, javax.swing.GroupLayout.DEFAULT_SIZE, 192, Short.MAX_VALUE)
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+ .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false)
+ .addComponent(SendButton, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
+ .addComponent(NewMessageScrollPane, javax.swing.GroupLayout.DEFAULT_SIZE, 51, Short.MAX_VALUE))
+ .addContainerGap())
+ );
+
+ pack();
+ }// //GEN-END:initComponents
+
+ private void SendButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_SendButtonActionPerformed
+ chat.sendMessage(NewMessageTextArea.getText());
+ MessagesTextArea.append("Me: " + NewMessageTextArea.getText() + "\n");
+ NewMessageTextArea.setText(null);
+ }//GEN-LAST:event_SendButtonActionPerformed
+
+ /**
+ * @param args the command line arguments
+ */
+ public static void main(String args[]) {
+ java.awt.EventQueue.invokeLater(new Runnable() {
+
+ @Override
+ public void run() {
+ new ChatFrame();
+ }
+ });
+ }
+
+
+ public void startChat() {
+ MessagesTextArea.append("Connecting...");
+ chat = new Chat(this);
+ chat.start();
+ }
+
+ // Variables declaration - do not modify//GEN-BEGIN:variables
+ private javax.swing.JScrollPane MessagesScrollPane;
+ private javax.swing.JTextArea MessagesTextArea;
+ private javax.swing.JScrollPane NewMessageScrollPane;
+ private javax.swing.JTextArea NewMessageTextArea;
+ private javax.swing.JLabel OnlineUsers;
+ private javax.swing.JLabel OnlineUsersLabel;
+ private javax.swing.JButton SendButton;
+ // End of variables declaration//GEN-END:variables
+
+ public void disableNewMessages() {
+ NewMessageTextArea.setEnabled(false);
+ SendButton.setEnabled(false);
+ }
+
+ public void enableNewMessages() {
+ NewMessageTextArea.setEnabled(true);
+ SendButton.setEnabled(true);
+ }
+
+ @Override
+ public void callback(JSONArray data) throws JSONException {}
+
+ @Override
+ public void on(String event, JSONObject... data) {
+ try {
+ if (event.equals("user message")) {
+ MessagesTextArea.append(data[0].getString("user") + ": " + data[0].getString("message") + "\n");
+ }
+
+ else if (event.equals("announcement")) {
+ MessagesTextArea.append(data[0].getString("user") + " " + data[0].getString("action") + "\n");
+ }
+
+ else if (event.equals("nicknames")) {
+ JSONArray names = data[0].names();
+ String str = "";
+ for (int i=0; i < names.length(); i++) {
+ if (i != 0)
+ str += ", ";
+ str += names.getString(i);
+ }
+ OnlineUsers.setText(str);
+ }
+ } catch (JSONException ex) {
+ ex.printStackTrace();
+ }
+ }
+
+ @Override
+ public void onMessage(String message) {}
+
+ @Override
+ public void onMessage(JSONObject json) {}
+
+ @Override
+ public void onConnect() {
+ MessagesTextArea.append("done!\n");
+ enableNewMessages();
+
+ String nickname = JOptionPane.showInputDialog(null, "Nickname", null, WIDTH);
+ if (!nickname.isEmpty()) {
+ chat.join(nickname);
+ MessagesTextArea.append("You joined as " + nickname + "\n");
+ }
+ }
+
+ @Override
+ public void onDisconnect() {
+ JOptionPane.showMessageDialog(null, "Connection lost", "Error", JOptionPane.ERROR_MESSAGE);
+ disableNewMessages();
+ }
+
+ @Override
+ public void onConnectFailure() {
+ MessagesTextArea.append("error!\n");
+ }
+
+}
\ No newline at end of file
diff --git a/examples/chat-server/app.js b/examples/chat-server/app.js
new file mode 100644
index 0000000..cbee63b
--- /dev/null
+++ b/examples/chat-server/app.js
@@ -0,0 +1,37 @@
+var http = require('http')
+ , io = require('socket.io');
+
+var app = http.createServer();
+app.listen(3000);
+
+console.log('Server running at http://127.0.0.1:3000/');
+
+// Socket.IO server
+var io = io.listen(app)
+ , nicknames = {};
+
+io.sockets.on('connection', function (socket) {
+ socket.on('user message', function (msg) {
+ socket.broadcast.emit('user message', {user: socket.nickname, message: msg.message});
+ });
+
+ socket.on('nickname', function (nick, fn) {
+ nickname = nick.nickname;
+ if (nicknames[nickname]) {
+ fn(true);
+ } else {
+ fn(false);
+ nicknames[nickname] = socket.nickname = nickname;
+ socket.broadcast.emit('announcement', {user: nickname, action: 'connected'});
+ io.sockets.emit('nicknames', nicknames);
+ }
+ });
+
+ socket.on('disconnect', function () {
+ if (!socket.nickname) return;
+
+ delete nicknames[socket.nickname];
+ socket.broadcast.emit('announcement', {user: socket.nickname, action: 'disconected'});
+ socket.broadcast.emit('nicknames', nicknames);
+ });
+});
diff --git a/src/com/clwillingham/socket/io/AckCallback.java b/src/com/clwillingham/socket/io/AckCallback.java
index 57d2e80..edc4d38 100644
--- a/src/com/clwillingham/socket/io/AckCallback.java
+++ b/src/com/clwillingham/socket/io/AckCallback.java
@@ -6,15 +6,15 @@
public abstract class AckCallback {
- private JSONObject requestData;
+ private JSONObject requestData;
- public abstract void callback(JSONArray data) throws JSONException;
+ public abstract void callback(JSONArray data) throws JSONException;
- public JSONObject getRequestData() {
- return requestData;
- }
+ public JSONObject getRequestData() {
+ return requestData;
+ }
- public void setRequestData(JSONObject requestData) {
- this.requestData = requestData;
- }
+ public void setRequestData(JSONObject requestData) {
+ this.requestData = requestData;
+ }
}
diff --git a/src/com/clwillingham/socket/io/IOBeat.java b/src/com/clwillingham/socket/io/IOBeat.java
index c6d3eb8..7684ac1 100644
--- a/src/com/clwillingham/socket/io/IOBeat.java
+++ b/src/com/clwillingham/socket/io/IOBeat.java
@@ -1,41 +1,39 @@
package com.clwillingham.socket.io;
-import java.io.IOException;
+import com.clwillingham.socket.io.log.Log;
import java.util.TimerTask;
public class IOBeat extends TimerTask {
- private IOWebSocket socket;
- private boolean running = false;
+ private IOWebSocket socket;
+ private boolean running = false;
- public IOBeat(IOWebSocket socket){
- this.socket = socket;
- }
+ public IOBeat(IOWebSocket socket){
+ this.socket = socket;
+ }
- @Override
- public void run() {
- // TODO Auto-generated method stub
- if(running){
- try {
- socket.send("2::"); //send heartbeat;
- System.out.println("HeartBeat Written to server");
- } catch (IOException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
- }
- }
-
- public void start(){
- running = true;
- }
-
- public void stop(){
- running = false;
+ @Override
+ public void run() {
+ if(running) {
+ try {
+ socket.send("2::"); //send heartbeat;
+ Log.info("HeartBeat Written to server");
+ } catch (Exception e) {
+ Log.error(e.getMessage());
+ }
}
+ }
- public boolean isRunning(){
- return running;
- }
+ public void start() {
+ running = true;
+ }
+
+ public void stop() {
+ running = false;
+ }
+
+ public boolean isRunning() {
+ return running;
+ }
-}
+}
\ No newline at end of file
diff --git a/src/com/clwillingham/socket/io/IOMessage.java b/src/com/clwillingham/socket/io/IOMessage.java
index 0eb0d28..b17704b 100644
--- a/src/com/clwillingham/socket/io/IOMessage.java
+++ b/src/com/clwillingham/socket/io/IOMessage.java
@@ -1,127 +1,129 @@
package com.clwillingham.socket.io;
+import com.clwillingham.socket.io.log.Log;
+
public class IOMessage {
- public static final int DISCONNECT = 0;
- public static final int CONNECT = 1;
- public static final int HEARTBEAT = 2;
- public static final int MESSAGE = 3;
- public static final int JSONMSG = 4;
- public static final int EVENT = 5;
- public static final int ACK = 6;
- public static final int ERROR = 7;
-
- private int type;
- private int id = -1;
- private String endpoint = "";
- private String messageData;
- private boolean ack = false;
-
- public IOMessage(int type, int id, String endpoint, String data){
- this.type = type;
- this.id = id;
- this.endpoint = endpoint;
- this.messageData = data;
- }
-
- public IOMessage(int type, String endpoint, String data) {
- this.type = type;
- this.endpoint = endpoint;
- this.messageData = data;
- }
-
- public IOMessage(){
-
- }
-
-
- public static IOMessage parseMsg(String message){
- String[] content = message.split(":", 4);
- IOMessage msg = new IOMessage();
- msg.setType(Integer.parseInt(content[0]));
-
- if(message.endsWith("::")){
- msg.setId(-1);
- msg.setMessageData("");
- msg.setEndpoint("");
- return msg;
- }
- System.out.println(content[1]);
- if(!content[1].equals("")){
- msg.setId(Integer.parseInt(content[1]));
- }
- if(!content[2].equals("")){
- msg.setEndpoint(content[2]);
- }
- if(content.length > 3 && !content[3].equals("")){
- msg.setMessageData(content[3]);
- }
- return msg;
- }
-
- public String toString(){
- if(id == -1 && endpoint.equals("") && messageData.equals("")){
- return type+"::";
- }
- else if(id == -1 && endpoint.equals("")){
- return type+":::"+messageData;
- }
- else if(id > -1){
- String idAck = ack ? "+" : "";
- return type + ":" + id + idAck + ":" + endpoint + ":" + messageData;
- }
- else{
- return type+"::"+endpoint+":"+messageData;
- }
- }
-
-
- public void setType(int type) {
- this.type = type;
- }
-
-
- public int getType() {
- return type;
- }
-
-
- public void setId(int id) {
- this.id = id;
- }
-
-
- public int getId() {
- return id;
- }
-
-
- public void setEndpoint(String endpoint) {
- this.endpoint = endpoint;
- }
-
-
- public String getEndpoint() {
- return endpoint;
- }
-
-
- public void setMessageData(String messageData) {
- this.messageData = messageData;
- }
-
-
- public String getMessageData() {
- return messageData;
- }
-
-
- public void setAck(boolean ack) {
- this.ack = ack;
- }
-
-
- public boolean getAck() {
- return ack;
- }
+ public static final int DISCONNECT = 0;
+ public static final int CONNECT = 1;
+ public static final int HEARTBEAT = 2;
+ public static final int MESSAGE = 3;
+ public static final int JSONMSG = 4;
+ public static final int EVENT = 5;
+ public static final int ACK = 6;
+ public static final int ERROR = 7;
+
+ private int type;
+ private int id = -1;
+ private String endpoint = "";
+ private String messageData;
+ private boolean ack = false;
+
+ public IOMessage(int type, int id, String endpoint, String data){
+ this.type = type;
+ this.id = id;
+ this.endpoint = endpoint;
+ this.messageData = data;
+ }
+
+ public IOMessage(int type, String endpoint, String data) {
+ this.type = type;
+ this.endpoint = endpoint;
+ this.messageData = data;
+ }
+
+ public IOMessage() {}
+
+ public static IOMessage parseMsg(String message){
+ String[] content = message.split(":", 4);
+ IOMessage msg = new IOMessage();
+ msg.setType(Integer.parseInt(content[0]));
+
+ if (message.endsWith("::")) {
+ msg.setId(-1);
+ msg.setMessageData("");
+ msg.setEndpoint("");
+ return msg;
+ }
+
+ Log.info(content[1]);
+
+ if (!content[1].equals("")){
+ msg.setId(Integer.parseInt(content[1]));
+ }
+ if (!content[2].equals("")){
+ msg.setEndpoint(content[2]);
+ }
+ if (content.length > 3 && !content[3].equals("")){
+ msg.setMessageData(content[3]);
+ }
+
+ return msg;
+ }
+
+ public String toString(){
+ if (id == -1 && endpoint.equals("") && messageData.equals("")){
+ return type+"::";
+ }
+ else if (id == -1 && endpoint.equals("")){
+ return type+":::"+messageData;
+ }
+ else if (id > -1){
+ String idAck = ack ? "+" : "";
+ return type + ":" + id + idAck + ":" + endpoint + ":" + messageData;
+ }
+ else {
+ return type+"::"+endpoint+":"+messageData;
+ }
+ }
+
+
+ public void setType(int type) {
+ this.type = type;
+ }
+
+
+ public int getType() {
+ return type;
+ }
+
+
+ public void setId(int id) {
+ this.id = id;
+ }
+
+
+ public int getId() {
+ return id;
+ }
+
+
+ public void setEndpoint(String endpoint) {
+ this.endpoint = endpoint;
+ }
+
+
+ public String getEndpoint() {
+ return endpoint;
+ }
+
+
+ public void setMessageData(String messageData) {
+ this.messageData = messageData;
+ }
+
+
+ public String getMessageData() {
+ return messageData;
+ }
+
+
+ public void setAck(boolean ack) {
+ this.ack = ack;
+ }
+
+
+ public boolean getAck() {
+ return ack;
+ }
}
diff --git a/src/com/clwillingham/socket/io/IOSocket.java b/src/com/clwillingham/socket/io/IOSocket.java
index e5c9f4e..4d2aafd 100644
--- a/src/com/clwillingham/socket/io/IOSocket.java
+++ b/src/com/clwillingham/socket/io/IOSocket.java
@@ -1,5 +1,6 @@
package com.clwillingham.socket.io;
+import com.clwillingham.socket.io.log.Log;
import java.io.IOException;
import java.io.InputStream;
import java.net.URI;
@@ -15,30 +16,29 @@
import org.json.JSONObject;
public class IOSocket {
-
- private IOWebSocket webSocket;
- private URL connection;
- private String sessionID;
- private int heartTimeout;
- private int closingTimeout;
- private int connectTimeout = 10000;
- private String[] protocals;
- private final String webSocketAddress;
+ private IOWebSocket webSocket;
+ private URL connection;
+ private String sessionID;
+ private int heartTimeout;
+ private int closingTimeout;
+ private int connectTimeout = 10000;
+ private String[] protocals;
+ private final String webSocketAddress;
private final String namespace;
- private final MessageCallback callback;
- private Timer timer;
+ private final MessageCallback callback;
+ private Timer timer;
- private int ackCount = 0;
- private HashMap ackCallbacks = new HashMap();
+ private int ackCount = 0;
+ private HashMap ackCallbacks = new HashMap();
- private boolean connecting;
- private boolean connected;
- private boolean open;
+ private boolean connecting;
+ private boolean connected;
+ private boolean open;
- public IOSocket(String address, MessageCallback callback){
-
+ public IOSocket(String address, MessageCallback callback) {
// check for socket.io namespace
int i = address.lastIndexOf("/");
+
if (address.charAt(i-1) != '/') {
namespace = address.substring(i);
webSocketAddress = address.substring(0, i);
@@ -47,109 +47,106 @@ public IOSocket(String address, MessageCallback callback){
webSocketAddress = address;
}
- this.callback = callback;
- }
+ this.callback = callback;
+ }
- public void connect() {
- synchronized(this) {
- connecting = true;
- }
-
- timer = new Timer();
- timer.schedule(new ConnectTimeout(), connectTimeout);
-
+ public void connect() {
+ synchronized(this) {
+ connecting = true;
+ }
+
+ timer = new Timer();
+ timer.schedule(new ConnectTimeout(), connectTimeout);
+
(new Thread(new Handshake())).start();
- }
-
- public void emit(String event, JSONObject... message) throws IOException {
- try {
- JSONObject data = new JSONObject();
- JSONArray args = new JSONArray();
- for (JSONObject arg : message) {
- args.put(arg);
- }
- data.put("name", event);
- data.put("args", args);
- IOMessage packet = new IOMessage(IOMessage.EVENT, "", data.toString());
- webSocket.sendMessage(packet);
- } catch (JSONException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
- }
-
- public void emit(String event, JSONObject message, AckCallback callback) throws IOException {
- try {
- JSONObject data = new JSONObject();
- data.put("name", event);
- data.put("args", message);
- IOMessage packet = new IOMessage(IOMessage.EVENT, addAcknowledge(callback, message), "", data.toString());
- packet.setAck(true);
- webSocket.sendMessage(packet);
- } catch (JSONException e) {
- e.printStackTrace();
- }
- }
-
- public void send(String message) throws IOException {
- IOMessage packet = new IOMessage(IOMessage.MESSAGE, "", message);
- webSocket.sendMessage(packet);
- }
-
- public synchronized void disconnect() {
- if (connected) {
- try {
- if (open) {
- webSocket.sendMessage(new IOMessage(IOMessage.DISCONNECT, "", ""));
- }
- } catch (IOException e) {
- e.printStackTrace();
- }
-
- onDisconnect();
- }
- }
-
- synchronized void onOpen() {
- open = true;
- }
-
- synchronized void onClose() {
- open = false;
- }
-
- synchronized void onConnect() {
-
- if (!connected) {
- connected = true;
- connecting = false;
-
- callback.onConnect();
- }
- }
+ }
- synchronized void onDisconnect() {
- boolean wasConnected = connected;
-
- connected = false;
- connecting = false;
-
- if (open) {
- try {
- webSocket.close();
- } catch (IOException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
-
- }
-
- if (wasConnected) {
- callback.onDisconnect();
-
- //TODO: reconnect
- }
- }
+ public void emit(String event, JSONObject... message) throws IOException {
+ try {
+ JSONObject data = new JSONObject();
+ JSONArray args = new JSONArray();
+ for (JSONObject arg : message) {
+ args.put(arg);
+ }
+ data.put("name", event);
+ data.put("args", args);
+ IOMessage packet = new IOMessage(IOMessage.EVENT, "", data.toString());
+ webSocket.sendMessage(packet);
+ } catch (JSONException e) {
+ Log.error(e.getMessage());
+ } catch (InterruptedException e) {
+ Log.error(e.getMessage());
+ }
+ }
+
+ public void emit(String event, JSONObject message, AckCallback callback) throws IOException {
+ try {
+ JSONObject data = new JSONObject();
+ data.put("name", event);
+ data.put("args", message);
+ IOMessage packet = new IOMessage(IOMessage.EVENT, addAcknowledge(callback, message), "", data.toString());
+ packet.setAck(true);
+ webSocket.sendMessage(packet);
+ } catch (JSONException e) {
+ Log.error(e.getMessage());
+ } catch (InterruptedException e) {
+ Log.error(e.getMessage());
+ }
+ }
+
+ public void send(String message) throws InterruptedException {
+ IOMessage packet = new IOMessage(IOMessage.MESSAGE, "", message);
+ webSocket.sendMessage(packet);
+ }
+
+ public synchronized void disconnect() {
+ if (connected) {
+ try {
+ if (open) {
+ webSocket.sendMessage(new IOMessage(IOMessage.DISCONNECT, "", ""));
+ }
+ } catch (InterruptedException e) {
+ Log.error(e.getMessage());
+ }
+ onDisconnect();
+ }
+ }
+
+ synchronized void onOpen() {
+ open = true;
+ }
+
+ synchronized void onClose() {
+ open = false;
+ }
+
+ synchronized void onConnect() {
+ if (!connected) {
+ connected = true;
+ connecting = false;
+
+ callback.onConnect();
+ }
+ }
+
+ synchronized void onDisconnect() {
+ boolean wasConnected = connected;
+
+ connected = false;
+ connecting = false;
+
+ if (open) {
+ try {
+ webSocket.close();
+ } catch (Exception e) {
+ Log.error(e.getMessage());
+ }
+ }
+
+ if (wasConnected) {
+ callback.onDisconnect();
+ }
+ }
private synchronized void onConnectFailure() {
connecting = false;
@@ -158,94 +155,93 @@ private synchronized void onConnectFailure() {
callback.onConnectFailure();
}
- public void onAcknowledge(int ackId, JSONArray data) {
- AckCallback ackCallback = ackCallbacks.get(ackId);
- if (ackCallback != null) {
- try {
- ackCallback.callback(data);
- } catch (JSONException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
- ackCallbacks.remove(ackId);
- }
- }
-
- public synchronized boolean isConnected() {
- return connected;
- }
-
- public synchronized boolean isConnecting() {
- return connecting;
- }
-
- public boolean isOpen() {
- return open;
- }
+ public void onAcknowledge(int ackId, JSONArray data) {
+ AckCallback ackCallback = ackCallbacks.get(ackId);
+ if (ackCallback != null) {
+ try {
+ ackCallback.callback(data);
+ } catch (JSONException e) {
+ Log.error(e.getMessage());
+ }
+ ackCallbacks.remove(ackId);
+ }
+ }
- public void setConnection(URL connection) {
- this.connection = connection;
- }
-
- private int addAcknowledge(AckCallback cb, JSONObject message) {
- if (cb != null) {
- cb.setRequestData(message);
- ackCount++;
- ackCallbacks.put(ackCount, cb);
- return ackCount;
- }
-
- return -1;
- }
-
-
- public URL getConnection() {
- return connection;
- }
-
- public void setConnectTimeout(int connectTimeout) {
- this.connectTimeout = connectTimeout;
- }
-
- public int getConnectTimeout() {
- return connectTimeout;
- }
+ public synchronized boolean isConnected() {
+ return connected;
+ }
- public void setHeartTimeout(int heartTimeOut) {
- this.heartTimeout = heartTimeOut;
- }
+ public synchronized boolean isConnecting() {
+ return connecting;
+ }
- public int getHeartTimeout() {
- return heartTimeout;
- }
-
- public void setClosingTimeout(int closingTimeout) {
- this.closingTimeout = closingTimeout;
- }
+ public boolean isOpen() {
+ return open;
+ }
+
+ public void setConnection(URL connection) {
+ this.connection = connection;
+ }
- public int getClosingTimeout() {
- return closingTimeout;
- }
+ private int addAcknowledge(AckCallback cb, JSONObject message) {
+ if (cb != null) {
+ cb.setRequestData(message);
+ ackCount++;
+ ackCallbacks.put(ackCount, cb);
+ return ackCount;
+ }
+
+ return -1;
+ }
- public void setSessionID(String sessionID) {
- this.sessionID = sessionID;
- }
+ public URL getConnection() {
+ return connection;
+ }
+ public void setConnectTimeout(int connectTimeout) {
+ this.connectTimeout = connectTimeout;
+ }
- public String getSessionID() {
- return sessionID;
- }
+ public int getConnectTimeout() {
+ return connectTimeout;
+ }
+ public void setHeartTimeout(int heartTimeOut) {
+ this.heartTimeout = heartTimeOut;
+ }
- public void setProtocals(String[] protocals) {
- this.protocals = protocals;
- }
+ public int getHeartTimeout() {
+ return heartTimeout;
+ }
+ public void setClosingTimeout(int closingTimeout) {
+ this.closingTimeout = closingTimeout;
+ }
- public String[] getProtocals() {
- return protocals;
- }
+ public int getClosingTimeout() {
+ return closingTimeout;
+ }
+
+
+ public void setSessionID(String sessionID) {
+ this.sessionID = sessionID;
+ }
+
+
+ public String getSessionID() {
+ return sessionID;
+ }
+
+
+ public void setProtocals(String[] protocals) {
+ this.protocals = protocals;
+ }
+
+
+ public String[] getProtocals() {
+ return protocals;
+ }
private synchronized void onHandshakeSuccess() {
if (!connecting) {
@@ -272,43 +268,47 @@ public void run() {
// process handshake response
// example: 4d4f185e96a7b:15:10:websocket,xhr-polling
- if(response.contains(":")) {
+ if (response.contains(":")) {
String[] data = response.split(":");
setSessionID(data[0]);
setHeartTimeout(Integer.parseInt(data[1]) * 1000);
setClosingTimeout(Integer.parseInt(data[2]) * 1000);
setProtocals(data[3].split(","));
+ Log.info("Handshaked: " + data[0]);
onHandshakeSuccess();
} else {
+ Log.error("Response error: " + response.toString());
onConnectFailure();
}
} catch (IOException e) {
+ Log.error(e.getMessage());
onConnectFailure();
}
}
}
- private class ConnectTimeout extends TimerTask {
- @Override
- public void run() {
- synchronized(IOSocket.this) {
- if (connected || !connecting) {
- return;
- }
- connecting = false;
-
- if (webSocket != null) {
- try {
- webSocket.close();
- } catch (IOException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
- }
- onConnectFailure();
- }
- }
- }
-}
+ private class ConnectTimeout extends TimerTask {
+ @Override
+ public void run() {
+ synchronized(IOSocket.this) {
+ if (connected || !connecting) {
+ return;
+ }
+ connecting = false;
+
+ if (webSocket != null) {
+ try {
+ webSocket.close();
+ } catch (Exception e) {
+ Log.error(e.getMessage());
+ }
+ }
+ Log.error("Connection timed out");
+ onConnectFailure();
+ }
+ }
+ }
+
+}
\ No newline at end of file
diff --git a/src/com/clwillingham/socket/io/IOWebSocket.java b/src/com/clwillingham/socket/io/IOWebSocket.java
index 5d756eb..47d168c 100644
--- a/src/com/clwillingham/socket/io/IOWebSocket.java
+++ b/src/com/clwillingham/socket/io/IOWebSocket.java
@@ -1,9 +1,10 @@
package com.clwillingham.socket.io;
-import java.io.IOException;
+import com.clwillingham.socket.io.log.Log;
import java.net.URI;
import java.util.Timer;
import java.util.TimerTask;
+import net.tootallnate.websocket.Handshakedata;
import org.json.JSONArray;
import org.json.JSONException;
@@ -12,178 +13,169 @@
import net.tootallnate.websocket.WebSocketClient;
public class IOWebSocket extends WebSocketClient {
-
- private Timer closeTimeout;
- private MessageCallback callback;
- private IOSocket ioSocket;
- private static int currentID = 0;
- private String namespace;
-
- public IOWebSocket(URI arg0, IOSocket ioSocket, MessageCallback callback) {
- super(arg0);
- this.callback = callback;
- this.ioSocket = ioSocket;
- }
-
-
- @Override
- public void onIOError(IOException arg0) {
- // TODO Auto-generated method stub
-
- }
-
- @Override
- public void onMessage(String arg0) {
- // The javascript socket.io client doesn't seem
- // to use the hearbeat timeout at all, just the close
- // timeout.
- clearCloseTimeout();
- setCloseTimeout();
-
- IOMessage message = IOMessage.parseMsg(arg0);
-
- switch (message.getType()) {
- case IOMessage.HEARTBEAT:
- try {
- send("2::");
- System.out.println("HeartBeat written to server");
- } catch (IOException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
- break;
-
- case IOMessage.MESSAGE:
- callback.onMessage(message.getMessageData());
- break;
-
- case IOMessage.JSONMSG:
- try {
- callback.onMessage(new JSONObject(message.getMessageData()));
- } catch (JSONException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
- break;
-
- case IOMessage.EVENT:
- try {
- JSONObject event = new JSONObject(message.getMessageData());
- JSONArray args = event.getJSONArray("args");
- JSONObject[] argsArray = new JSONObject[args.length()];
- for (int i = 0; i < args.length(); i++) {
- argsArray[i] = args.getJSONObject(i);
- }
- String eventName = event.getString("name");
-
- callback.on(eventName, argsArray);
- } catch (JSONException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
- break;
-
- case IOMessage.CONNECT:
- ioSocket.onConnect();
- break;
-
- case IOMessage.ACK:
- String[] parts = message.getMessageData().split("\\+", 2);
- int ackId = Integer.parseInt(parts[0]);
-
- JSONArray data = null;
- if (parts.length > 1) {
- try {
- data = new JSONArray(parts[1]);
- } catch (JSONException e) {
- e.printStackTrace();
- }
- }
-
- ioSocket.onAcknowledge(ackId, data);
- break;
-
- case IOMessage.ERROR:
- case IOMessage.DISCONNECT:
- //TODO
- break;
- }
- }
-
- @Override
- public void onOpen() {
- try {
- if (!namespace.equals("")) {
+ private Timer closeTimeout;
+ private MessageCallback callback;
+ private IOSocket ioSocket;
+ private static int currentID = 0;
+ private String namespace;
+
+ public IOWebSocket(URI arg0, IOSocket ioSocket, MessageCallback callback) {
+ super(arg0);
+ this.callback = callback;
+ this.ioSocket = ioSocket;
+ }
+
+ @Override
+ public void onMessage(String arg0) {
+ // The javascript socket.io client doesn't seem
+ // to use the hearbeat timeout at all, just the close
+ // timeout.
+ clearCloseTimeout();
+ setCloseTimeout();
+
+ IOMessage message = IOMessage.parseMsg(arg0);
+
+ switch (message.getType()) {
+ case IOMessage.HEARTBEAT:
+ try {
+ send("2::");
+ Log.info("HeartBeat written to server");
+ } catch (Exception e) {
+ Log.error(e.getMessage());
+ }
+ break;
+
+ case IOMessage.MESSAGE:
+ callback.onMessage(message.getMessageData());
+ break;
+
+ case IOMessage.JSONMSG:
+ try {
+ callback.onMessage(new JSONObject(message.getMessageData()));
+ } catch (JSONException e) {
+ Log.error(e.getMessage());
+ }
+ break;
+
+ case IOMessage.EVENT:
+ try {
+ JSONObject event = new JSONObject(message.getMessageData());
+ JSONArray args = event.getJSONArray("args");
+ JSONObject[] argsArray = new JSONObject[args.length()];
+ for (int i = 0; i < args.length(); i++) {
+ argsArray[i] = args.getJSONObject(i);
+ }
+ String eventName = event.getString("name");
+
+ callback.on(eventName, argsArray);
+ } catch (JSONException e) {
+ Log.error(e.getMessage());
+ }
+ break;
+
+ case IOMessage.CONNECT:
+ ioSocket.onConnect();
+ break;
+
+ case IOMessage.ACK:
+ String[] parts = message.getMessageData().split("\\+", 2);
+ int ackId = Integer.parseInt(parts[0]);
+
+ JSONArray data = null;
+ if (parts.length > 1) {
+ try {
+ data = new JSONArray(parts[1]);
+ } catch (JSONException e) {
+ Log.error(e.getMessage());
+ }
+ }
+
+ ioSocket.onAcknowledge(ackId, data);
+ break;
+
+ case IOMessage.ERROR:
+ case IOMessage.DISCONNECT:
+ break;
+ }
+ }
+
+ public void init(String path) throws InterruptedException {
+ send("1::"+path);
+ }
+
+ public void init(String path, String query) throws InterruptedException {
+ send("1::"+path+"?"+query);
+
+ }
+
+ public void sendMessage(IOMessage message) throws InterruptedException {
+ send(message.toString());
+ }
+
+ public void sendMessage(String message) throws InterruptedException {
+ send(new Message(message).toString());
+ }
+
+
+ public static int genID(){
+ currentID++;
+ return currentID;
+ }
+
+ public void setNamespace(String ns) {
+ namespace = ns;
+ }
+
+ public String getNamespace() {
+ return namespace;
+ }
+
+ private void setCloseTimeout() {
+ closeTimeout = new Timer();
+ closeTimeout.schedule(new CloseTask(), ioSocket.getClosingTimeout());
+ }
+
+ private void clearCloseTimeout() {
+ if (closeTimeout != null) {
+ closeTimeout.cancel();
+ closeTimeout = null;
+ }
+ }
+
+ @Override
+ public void onOpen(Handshakedata h) {
+ try {
+ if (!namespace.equals("")) {
init(namespace);
}
- } catch (IOException e) {
- e.printStackTrace();
- }
-
- ioSocket.onOpen();
-
- setCloseTimeout();
- }
-
- @Override
- public void onClose() {
- ioSocket.onClose();
- ioSocket.onDisconnect();
- }
-
- public void init(String path) throws IOException{
- send("1::"+path);
- }
-
- public void init(String path, String query) throws IOException{
- this.send("1::"+path+"?"+query);
-
- }
-
- public void sendMessage(IOMessage message) throws IOException{
- send(message.toString());
- }
-
- public void sendMessage(String message) throws IOException{
- send(new Message(message).toString());
- }
-
-
- public static int genID(){
- currentID++;
- return currentID;
- }
-
- public void setNamespace(String ns) {
- namespace = ns;
- }
-
- public String getNamespace() {
- return namespace;
- }
-
- private void setCloseTimeout() {
- closeTimeout = new Timer();
- closeTimeout.schedule(new CloseTask(), ioSocket.getClosingTimeout());
- }
-
- private void clearCloseTimeout() {
- if (closeTimeout != null) {
- closeTimeout.cancel();
- closeTimeout = null;
- }
- }
+ } catch (Exception e) {
+ Log.error(e.getMessage());
+ }
+
+ ioSocket.onOpen();
+ setCloseTimeout();
+ }
+
+ @Override
+ public void onClose(int i, String string, boolean bln) {
+ ioSocket.onClose();
+ ioSocket.onDisconnect();
+ }
+
+ @Override
+ public void onError(Exception excptn) {
+
+ }
- private class CloseTask extends TimerTask {
- @Override
- public void run() {
- try {
- close();
- } catch (IOException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
- ioSocket.onDisconnect();
- }
- }
+ private class CloseTask extends TimerTask {
+ @Override
+ public void run() {
+ try {
+ close();
+ } catch (Exception e) {
+ Log.error(e.getMessage());
+ }
+ ioSocket.onDisconnect();
+ }
+ }
}
diff --git a/src/com/clwillingham/socket/io/Message.java b/src/com/clwillingham/socket/io/Message.java
index b6b5526..71920e3 100644
--- a/src/com/clwillingham/socket/io/Message.java
+++ b/src/com/clwillingham/socket/io/Message.java
@@ -1,8 +1,8 @@
package com.clwillingham.socket.io;
-public class Message extends IOMessage{
+public class Message extends IOMessage {
- public Message(String message){
- super(IOMessage.MESSAGE, -1, "", message);
- }
+ public Message(String message) {
+ super(IOMessage.MESSAGE, -1, "", message);
+ }
}
diff --git a/src/com/clwillingham/socket/io/MessageCallback.java b/src/com/clwillingham/socket/io/MessageCallback.java
index aa7b6bd..7bc9c5e 100644
--- a/src/com/clwillingham/socket/io/MessageCallback.java
+++ b/src/com/clwillingham/socket/io/MessageCallback.java
@@ -3,10 +3,10 @@
import org.json.JSONObject;
public interface MessageCallback {
- public void on(String event, JSONObject... data);
- public void onMessage(String message);
- public void onMessage(JSONObject json);
- public void onConnect();
- public void onDisconnect();
- public void onConnectFailure();
+ public void on(String event, JSONObject... data);
+ public void onMessage(String message);
+ public void onMessage(JSONObject json);
+ public void onConnect();
+ public void onDisconnect();
+ public void onConnectFailure();
}
diff --git a/src/com/clwillingham/socket/io/log/DefaultLog.java b/src/com/clwillingham/socket/io/log/DefaultLog.java
new file mode 100644
index 0000000..1ad49bb
--- /dev/null
+++ b/src/com/clwillingham/socket/io/log/DefaultLog.java
@@ -0,0 +1,20 @@
+package com.clwillingham.socket.io.log;
+
+public class DefaultLog implements LogAdapter {
+
+ @Override
+ public void info(String message) {
+ System.out.println("INFO: " + message);
+ }
+
+ @Override
+ public void warning(String message) {
+ System.out.println("WARNING: " + message);
+ }
+
+ @Override
+ public void error(String message) {
+ System.err.println("ERROR: " + message);
+ }
+
+}
diff --git a/src/com/clwillingham/socket/io/log/Log.java b/src/com/clwillingham/socket/io/log/Log.java
new file mode 100644
index 0000000..0a32877
--- /dev/null
+++ b/src/com/clwillingham/socket/io/log/Log.java
@@ -0,0 +1,28 @@
+package com.clwillingham.socket.io.log;
+
+public class Log {
+ public static LogAdapter logger;
+
+ public static LogAdapter getInstance() {
+ if (logger == null) {
+ logger = new DefaultLog();
+ }
+ return logger;
+ }
+
+ public static void setInstance(LogAdapter adapter) {
+ logger = adapter;
+ }
+
+ public static void info(String message) {
+ getInstance().info(message);
+ }
+
+ public static void warning(String message) {
+ getInstance().warning(message);
+ }
+
+ public static void error(String message) {
+ getInstance().error(message);
+ }
+}
diff --git a/src/com/clwillingham/socket/io/log/LogAdapter.java b/src/com/clwillingham/socket/io/log/LogAdapter.java
new file mode 100644
index 0000000..6455c7b
--- /dev/null
+++ b/src/com/clwillingham/socket/io/log/LogAdapter.java
@@ -0,0 +1,7 @@
+package com.clwillingham.socket.io.log;
+
+public interface LogAdapter {
+ public void info(String message);
+ public void warning(String message);
+ public void error(String message);
+}