/** * The MIT License * Copyright (c) 2010 Tad Glines * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ package com.glines.socketio.sample.chat; import java.io.IOException; import java.util.Collections; import java.util.Queue; import java.util.concurrent.ConcurrentLinkedQueue; import java.util.concurrent.atomic.AtomicInteger; import javax.servlet.http.HttpServletRequest; import com.glines.socketio.server.SocketIOOutbound; import org.eclipse.jetty.util.ajax.JSON; import org.eclipse.jetty.util.log.Log; import com.glines.socketio.common.DisconnectReason; import com.glines.socketio.common.SocketIOException; import com.glines.socketio.server.SocketIOFrame; import com.glines.socketio.server.SocketIOInbound; import com.glines.socketio.server.SocketIOServlet; public class ChatSocketServlet extends SocketIOServlet { private static final long serialVersionUID = 1L; private AtomicInteger ids = new AtomicInteger(1); private Queue<ChatConnection> connections = new ConcurrentLinkedQueue<ChatConnection>(); private class ChatConnection implements SocketIOInbound { private volatile SocketIOOutbound outbound = null; private Integer sessionId = ids.getAndIncrement(); @Override public void onConnect(SocketIOOutbound outbound) { this.outbound = outbound; connections.offer(this); try { outbound.sendMessage(SocketIOFrame.JSON_MESSAGE_TYPE, JSON.toString( Collections.singletonMap("welcome", "Welcome to Socket.IO Chat!"))); } catch (SocketIOException e) { outbound.disconnect(); } broadcast(SocketIOFrame.JSON_MESSAGE_TYPE, JSON.toString( Collections.singletonMap("announcement", sessionId + " connected"))); } @Override public void onDisconnect(DisconnectReason reason, String errorMessage) { this.outbound = null; connections.remove(this); broadcast(SocketIOFrame.JSON_MESSAGE_TYPE, JSON.toString( Collections.singletonMap("announcement", sessionId + " disconnected"))); } @Override public void onMessage(int messageType, String message) { Log.debug("Recieved: " + message); if (message.equals("/rclose")) { outbound.close(); } else if (message.equals("/rdisconnect")) { outbound.disconnect(); } else if (message.startsWith("/sleep")) { int sleepTime = 1; String parts[] = message.split("\\s+"); if (parts.length == 2) { sleepTime = Integer.parseInt(parts[1]); } try { Thread.sleep(sleepTime * 1000); } catch (InterruptedException e) { // Ignore } try { outbound.sendMessage(SocketIOFrame.JSON_MESSAGE_TYPE, JSON.toString( Collections.singletonMap("message","Slept for " + sleepTime + " seconds."))); } catch (SocketIOException e) { outbound.disconnect(); } } else if (message.startsWith("/burst")) { int burstNum = 10; String parts[] = message.split("\\s+"); if (parts.length == 2) { burstNum = Integer.parseInt(parts[1]); } try { for (int i = 0; i < burstNum; i++) { Log.debug("**************************************** Sending burst message: " + i); outbound.sendMessage(SocketIOFrame.JSON_MESSAGE_TYPE, JSON.toString( Collections.singletonMap("message",new String[]{"Server", "Hi " + i + "0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF" + "0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF" + "0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF" + "0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF" + "0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF" + "0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF" + "0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF" + "0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF" }))); // outbound.sendMessage(SocketIOFrame.JSON_MESSAGE_TYPE, JSON.toString( // Collections.singletonMap("say","Hi " + i))); try { Thread.sleep(250); } catch (InterruptedException e) { // Do nothing } } } catch (Exception e) { Log.debug(e); // } catch (SocketIOException e) { // Log.debug(e); // outbound.disconnect(); } } else { broadcast(SocketIOFrame.JSON_MESSAGE_TYPE, JSON.toString( Collections.singletonMap("message", new String[]{sessionId.toString(), (String)message}))); } } private void broadcast(int messageType, String message) { Log.debug("Broadcasting: " + message); for(ChatConnection c: connections) { if (c != this) { try { c.outbound.sendMessage(messageType, message); } catch (IOException e) { c.outbound.disconnect(); } } } } } @Override protected SocketIOInbound doSocketIOConnect(HttpServletRequest request) { return new ChatConnection(); } }