Sketcher2 source code
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

241 lines
7.8 KiB

/**
*
*/
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<Integer, Connection> 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<Integer, Layer> 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<Integer, Connection> 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<Integer, Connection> 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<Integer, Layer> 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;
}
}