/** * */ package com.jotuntech.sketcher.server.command; import java.nio.ByteBuffer; import java.util.Map; import java.util.Map.Entry; import com.jotuntech.sketcher.common.BitmapUndoData; import com.jotuntech.sketcher.common.Canvas; import com.jotuntech.sketcher.common.Layer; import com.jotuntech.sketcher.common.Log; import com.jotuntech.sketcher.common.UndoEntry; import com.jotuntech.sketcher.common.User; import com.jotuntech.sketcher.server.AccessController; import com.jotuntech.sketcher.server.Command; import com.jotuntech.sketcher.server.CommandEntry; import com.jotuntech.sketcher.server.Connection; import com.jotuntech.sketcher.server.Server; /** * @author Thor Harald Johansen * */ public class SignInCommand implements Command { Integer peerKey; String login; String password; boolean viewer; public SignInCommand() { } public SignInCommand(Integer peerKey, String login, String password, boolean viewer) { this.peerKey = peerKey; this.login = login; this.password = password; this.viewer = viewer; } public void decode(ByteBuffer in) { peerKey = in.getInt(); viewer = in.get() != 0; int loginLength = (in.get() & 0xFF) + 1; StringBuffer loginBuffer = new StringBuffer(); for(int i = 0; i < loginLength; i++) { loginBuffer.append(in.getChar()); } login = loginBuffer.toString(); StringBuffer passwordBuffer = new StringBuffer(); while(in.remaining() >= 2) { passwordBuffer.append(in.getChar()); } password = passwordBuffer.toString(); } public void encode(ByteBuffer out) { out.putInt(peerKey); out.put((byte) (viewer ? 0xFF : 0x00)); out.put((byte) (login.length() - 1)); for(int i = 0; i < login.length(); i++) { out.putChar(login.charAt(i)); } for(int i = 0; i < password.length(); i++) { out.putChar(password.charAt(i)); } } public int perform(Server server, Connection connection) { AccessController ac = server.getAccessController(); if(!ac.isLoginAllowed(server, login, password)) { connection.getSendQueue().offer(new CommandEntry(0, new ServerMessageCommand("Access to Sketcher is denied."))); connection.setTimeOfDeath(System.currentTimeMillis() + 5000); return Connection.SEND_NONE; } password = new String(); /** Kill any zombies */ for(Map.Entry e : server.getConnectionMap().entrySet()) { Integer k = e.getKey(); Connection c = e.getValue(); User u = c.getUser(); if(u != null && u != connection.getUser() && u.getName().equalsIgnoreCase(login)) { /** Tell duplicate connection to die */ for(Connection c2 : server.getConnectionMap().values()) { c2.getSendQueue().offer(new CommandEntry(k, new SignOutCommand("Duplicate user removed"))); } c.setTimeOfDeath(System.currentTimeMillis()); } } /** Create user */ User user = new User(login); /** Assign proper viewer status */ viewer = ac.isViewer(server, user); user.setViewer(viewer); /** Fetch canvas for context */ Canvas canvas = server.getCanvas(); /** Tell client canvas size */ connection.getSendQueue().offer(new CommandEntry(0, new CanvasCommand(canvas.getWidth(), canvas.getHeight()))); /** Send MOTD if there is any */ String motd = server.getMOTD(); if(motd != null) { connection.getSendQueue().offer(new CommandEntry(0, new ServerMessageCommand(motd))); } /** Assign proper peer key */ peerKey = server.getConnectionMap().getKeyForValue(connection); /** Tell client its signed in */ connection.getSendQueue().offer(new CommandEntry(peerKey, this)); //int layerBytes = 0, inflatedBytes = 0; for(Entry e : server.getCanvas().getLayerMap().entrySet()) { Integer k = e.getKey(); Layer l = e.getValue(); connection.getSendQueue().offer(new CommandEntry(0, new CreateLayerCommand(k, l.getType(), l.getName()))); connection.getSendQueue().offer(new CommandEntry(0, new ServerMessageCommand("Loading layer " + l.getName()))); l.reset(); for(byte[] data = l.encode(); data != null; data = l.encode()) { connection.getSendQueue().offer(new CommandEntry(0, new LayerDataCommand(k, false, data))); //layerBytes += data.length; //inflatedBytes += BitmapTile.SIZE * BitmapTile.SIZE * 4; } } /** Send user list */ for(Map.Entry e : server.getConnectionMap().entrySet()) { Integer k = e.getKey(); Connection c = e.getValue(); User u = c.getUser(); if(c.hasTimeOfDeath() || u == null || u == connection.getUser()) { continue; } /** Send user name */ connection.getSendQueue().offer(new CommandEntry(k, new SignInCommand(e.getKey(), u.getName(), new String(), u.isViewer()))); /** If brush is set for user, then send brush */ if(u.getBrush() != null) { connection.getSendQueue().offer(new CommandEntry(k, new SetBrushCommand(u.getBrush()))); } /** Send color for user */ connection.getSendQueue().offer(new CommandEntry(k, new SetColorCommand(u.getColor()))); /** If layer is set for user, then send layer */ Integer layerKey = canvas.getLayerMap().getKeyForValue(u.getLayer()); if(layerKey != null) { connection.getSendQueue().offer(new CommandEntry(k, new SetLayerCommand(layerKey))); } /** If cursor is set for user, then send cursor */ if(u.getCursor() != null) { connection.getSendQueue().offer(new CommandEntry(k, new CursorCommand(u.getCursor()))); } } /** Send user associated data */ for(Map.Entry e : server.getConnectionMap().entrySet()) { Integer k = e.getKey(); Connection c = e.getValue(); User u = c.getUser(); if(c.hasTimeOfDeath() || u == null || u == connection.getUser()) { continue; } connection.getSendQueue().offer(new CommandEntry(0, new ServerMessageCommand("Loading temporary data for " + u.getName()))); /** Send phantom layer data */ Layer l = u.getPhantomLayer(); for(byte[] data = l.encode(); data != null; data = l.encode()) { connection.getSendQueue().offer(new CommandEntry(k, new LayerDataCommand(0, true, data))); //layerBytes += data.length; //inflatedBytes += BitmapTile.SIZE * BitmapTile.SIZE * 4; } /** Send undo deque */ for(UndoEntry ue : u.getUndoDeque()) { Integer layerKey = canvas.getLayerMap().getKeyForValue(ue.getLayer()); connection.getSendQueue().offer(new CommandEntry(k, new UndoEntryCommand(layerKey))); BitmapUndoData bud = (BitmapUndoData) ue.getUndoData(); bud.reset(); for(byte[] data = bud.encode(); data != null; data = bud.encode()) { connection.getSendQueue().offer(new CommandEntry(k, new UndoDataCommand(data))); } } } /** Assign user to connection */ connection.setUser(user); /** Notify connection map listeners */ server.getConnectionMap().change(); /** Add canvas as phantom layer listener */ user.getPhantomLayer().addImageObserver(server.getCanvas()); /** Let the user know that load is complete. */ connection.getSendQueue().offer(new CommandEntry(0, new ServerMessageCommand("Sketcher is ready."))); /** Log event */ Log.info(login + " has signed in."); /** HACK: Broadcast sign-in manually. */ for(Connection c : server.getConnectionMap().values()) { if(c.getUser() == user) { continue; } c.getSendQueue().offer(new CommandEntry(peerKey, this)); } /** Set and send default layer */ for(Map.Entry e : canvas.getLayerMap().entrySet()) { if("Doodle".equals(e.getValue().getName())) { user.setLayer(e.getValue()); for(Connection c : server.getConnectionMap().values()) { c.getSendQueue().offer(new CommandEntry(peerKey, new SetLayerCommand(e.getKey()))); } break; } } /** Return "silently" */ return Connection.SEND_NONE; } }