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
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;
|
|
}
|
|
}
|
|
|