From cac89ede5ad0f11a5636cdf2210b3d478340b3d3 Mon Sep 17 00:00:00 2001 From: Maxmtg Date: Sat, 13 Apr 2013 22:00:41 +0000 Subject: [PATCH] Server incubation --- .gitattributes | 20 +++ src/main/java/forge/net/IClientSocket.java | 7 + .../java/forge/net/IConnectionObserver.java | 9 ++ src/main/java/forge/net/NetServer.java | 124 ++++++++++++++++++ .../java/forge/net/client/INetClient.java | 17 +++ src/main/java/forge/net/client/NetClient.java | 48 +++++++ .../java/forge/net/client/package-info.java | 3 + .../forge/net/client/state/ClientState.java | 37 ++++++ .../client/state/ClientStateUnauthorized.java | 19 +++ .../forge/net/client/state/IClientState.java | 11 ++ .../forge/net/client/state/package-info.java | 3 + .../net/protocol/incoming/ChatPacket.java | 18 +++ .../net/protocol/incoming/EchoPacket.java | 19 +++ .../forge/net/protocol/incoming/Packet.java | 18 +++ .../net/protocol/incoming/PacketOpcode.java | 46 +++++++ .../net/protocol/incoming/UnknownPacket.java | 19 +++ .../net/protocol/incoming/package-info.java | 3 + .../net/protocol/outcoming/EchoMessage.java | 26 ++++ .../forge/net/protocol/outcoming/Message.java | 9 ++ .../outcoming/UnknownPacketMessage.java | 17 +++ .../java/forge/net/protocol/package-info.java | 3 + 21 files changed, 476 insertions(+) create mode 100644 src/main/java/forge/net/IClientSocket.java create mode 100644 src/main/java/forge/net/IConnectionObserver.java create mode 100644 src/main/java/forge/net/NetServer.java create mode 100644 src/main/java/forge/net/client/INetClient.java create mode 100644 src/main/java/forge/net/client/NetClient.java create mode 100644 src/main/java/forge/net/client/package-info.java create mode 100644 src/main/java/forge/net/client/state/ClientState.java create mode 100644 src/main/java/forge/net/client/state/ClientStateUnauthorized.java create mode 100644 src/main/java/forge/net/client/state/IClientState.java create mode 100644 src/main/java/forge/net/client/state/package-info.java create mode 100644 src/main/java/forge/net/protocol/incoming/ChatPacket.java create mode 100644 src/main/java/forge/net/protocol/incoming/EchoPacket.java create mode 100644 src/main/java/forge/net/protocol/incoming/Packet.java create mode 100644 src/main/java/forge/net/protocol/incoming/PacketOpcode.java create mode 100644 src/main/java/forge/net/protocol/incoming/UnknownPacket.java create mode 100644 src/main/java/forge/net/protocol/incoming/package-info.java create mode 100644 src/main/java/forge/net/protocol/outcoming/EchoMessage.java create mode 100644 src/main/java/forge/net/protocol/outcoming/Message.java create mode 100644 src/main/java/forge/net/protocol/outcoming/UnknownPacketMessage.java create mode 100644 src/main/java/forge/net/protocol/package-info.java diff --git a/.gitattributes b/.gitattributes index fe8bb1eafc4..079cffe58de 100644 --- a/.gitattributes +++ b/.gitattributes @@ -14286,7 +14286,27 @@ src/main/java/forge/model/BuildInfo.java -text src/main/java/forge/model/FModel.java svneol=native#text/plain src/main/java/forge/model/MultipleForgeJarsFoundError.java -text src/main/java/forge/model/package-info.java svneol=native#text/plain +src/main/java/forge/net/IClientSocket.java -text +src/main/java/forge/net/IConnectionObserver.java -text +src/main/java/forge/net/NetServer.java -text +src/main/java/forge/net/client/INetClient.java -text +src/main/java/forge/net/client/NetClient.java -text +src/main/java/forge/net/client/package-info.java -text +src/main/java/forge/net/client/state/ClientState.java -text +src/main/java/forge/net/client/state/ClientStateUnauthorized.java -text +src/main/java/forge/net/client/state/IClientState.java -text +src/main/java/forge/net/client/state/package-info.java -text src/main/java/forge/net/package-info.java -text +src/main/java/forge/net/protocol/incoming/ChatPacket.java -text +src/main/java/forge/net/protocol/incoming/EchoPacket.java -text +src/main/java/forge/net/protocol/incoming/Packet.java -text +src/main/java/forge/net/protocol/incoming/PacketOpcode.java -text +src/main/java/forge/net/protocol/incoming/UnknownPacket.java -text +src/main/java/forge/net/protocol/incoming/package-info.java -text +src/main/java/forge/net/protocol/outcoming/EchoMessage.java -text +src/main/java/forge/net/protocol/outcoming/Message.java -text +src/main/java/forge/net/protocol/outcoming/UnknownPacketMessage.java -text +src/main/java/forge/net/protocol/package-info.java -text src/main/java/forge/package-info.java svneol=native#text/plain src/main/java/forge/properties/ForgePreferences.java svneol=native#text/plain src/main/java/forge/properties/NewConstants.java svneol=native#text/plain diff --git a/src/main/java/forge/net/IClientSocket.java b/src/main/java/forge/net/IClientSocket.java new file mode 100644 index 00000000000..e99e1eae305 --- /dev/null +++ b/src/main/java/forge/net/IClientSocket.java @@ -0,0 +1,7 @@ +package forge.net; + +public interface IClientSocket { + boolean isOpen(); + void send(String message); + void close(String farewell); +} \ No newline at end of file diff --git a/src/main/java/forge/net/IConnectionObserver.java b/src/main/java/forge/net/IConnectionObserver.java new file mode 100644 index 00000000000..e5e7dc83881 --- /dev/null +++ b/src/main/java/forge/net/IConnectionObserver.java @@ -0,0 +1,9 @@ +package forge.net; + +public interface IConnectionObserver { + /** Notifies that the client is gone, it's too late to send anything */ + public void onConnectionClosed(); + + /** Notifies of an incoming message */ + public void onMessage(String data); +} \ No newline at end of file diff --git a/src/main/java/forge/net/NetServer.java b/src/main/java/forge/net/NetServer.java new file mode 100644 index 00000000000..a328295bc93 --- /dev/null +++ b/src/main/java/forge/net/NetServer.java @@ -0,0 +1,124 @@ +package forge.net; + +import java.io.IOException; +import java.net.URI; +import java.util.Set; +import java.util.concurrent.CopyOnWriteArraySet; + +import javax.servlet.http.HttpServletRequest; + +import org.eclipse.jetty.server.Server; +import org.eclipse.jetty.server.nio.SelectChannelConnector; +import org.eclipse.jetty.servlet.ServletContextHandler; +import org.eclipse.jetty.servlet.ServletHolder; +import org.eclipse.jetty.websocket.WebSocket; +import org.eclipse.jetty.websocket.WebSocketServlet; + + +import forge.error.BugReporter; +import forge.net.client.NetClient; + +/** + * TODO: Write javadoc for this type. + * + */ +public class NetServer { + + private final Server srv = new Server(); + private final Set _openSockets = new CopyOnWriteArraySet(); + + @SuppressWarnings("serial") + public class GameServlet extends WebSocketServlet + { + @Override + public WebSocket doWebSocketConnect(HttpServletRequest request, String protocol) { + System.out.printf("Connection from %s recieved%n", request.getRemoteAddr()); + return new ClientSocket(); + } + } + + + public class ClientSocket implements WebSocket.OnTextMessage, IClientSocket + { + private Connection _connection; + private IConnectionObserver _client; + + + @Override + public void onClose(int closeCode, String message) { + System.out.println("Lost connection: " + closeCode + ", " + message); + _openSockets.remove(_client); + _client.onConnectionClosed(); + } + + public void send(String data) { + try { + _connection.sendMessage(data); + } catch (IOException e) { + BugReporter.reportException(e); + } + } + + @Override + public void onMessage(String data) { + System.out.println("Received: " + data); + _client.onMessage(data); + } + + public boolean isOpen() { + return _connection.isOpen(); + } + + @Override + public void onOpen(Connection connection) { + _connection = connection; + _client = new NetClient(this); + _openSockets.add(this); + send("CardForge server welcomes you."); + } + + @Override + public void close(String farewell) { + _connection.close(1000, farewell); + } + } + + public void listen() { + if (!srv.isStarted()) + { + SelectChannelConnector connector= new SelectChannelConnector(); + connector.setPort(81); + srv.addConnector(connector); + + ServletContextHandler context = new ServletContextHandler(); + ServletHolder sh = new ServletHolder(new GameServlet()); + context.addServlet(sh, "/*"); + //context.setContextPath("/"); + srv.setHandler(context); + + URI serverUri = null; + try { + srv.start(); + int port = connector.getLocalPort(); + String host = connector.getHost(); + serverUri = new URI(String.format("ws://%s:%d/", host == null ? "localhost" : host ,port)); + } catch (Exception e) { + BugReporter.reportException(e); + } + + System.out.println("Server started @ " + serverUri); + } + else { + System.out.println("Server was already started"); + } + } + + public void stop() { + try { + srv.stop(); + } catch (Exception e) { + BugReporter.reportException(e); + } + } + +} diff --git a/src/main/java/forge/net/client/INetClient.java b/src/main/java/forge/net/client/INetClient.java new file mode 100644 index 00000000000..e1710e0b1cf --- /dev/null +++ b/src/main/java/forge/net/client/INetClient.java @@ -0,0 +1,17 @@ +package forge.net.client; + +import forge.net.protocol.outcoming.Message; + +/** + * TODO: Write javadoc for this type. + * + */ +public interface INetClient { + + /** + * TODO: Write javadoc for this method. + * @param echoMessage + */ + void send(Message echoMessage); + +} diff --git a/src/main/java/forge/net/client/NetClient.java b/src/main/java/forge/net/client/NetClient.java new file mode 100644 index 00000000000..d6dab980862 --- /dev/null +++ b/src/main/java/forge/net/client/NetClient.java @@ -0,0 +1,48 @@ +package forge.net.client; + +import forge.game.player.LobbyPlayer; +import forge.game.player.PlayerType; +import forge.net.IClientSocket; +import forge.net.IConnectionObserver; +import forge.net.client.state.ClientStateUnauthorized; +import forge.net.client.state.IClientState; +import forge.net.protocol.incoming.Packet; +import forge.net.protocol.incoming.PacketOpcode; +import forge.net.protocol.outcoming.Message; + +public class NetClient implements IConnectionObserver, INetClient{ + + private final IClientSocket socket; + private IClientState state = new ClientStateUnauthorized(this); + private LobbyPlayer player = null; + + public NetClient(IClientSocket clientSocket) { + socket = clientSocket; + } + + public void autorized() { + player = new LobbyPlayer(PlayerType.REMOTE, "Guest"); + } + + /* (non-Javadoc) + * @see forge.net.client.IConnectionObserver#onConnectionClosed() + */ + @Override + public void onConnectionClosed() { + // Tell the game, the client is gone. + } + + + @Override + public void onMessage(String data) { + Packet p = PacketOpcode.decode(data); + state.onPacket(p); + } + + + @Override + public void send(Message message) { + socket.send(message.toNetString()); + } + +} diff --git a/src/main/java/forge/net/client/package-info.java b/src/main/java/forge/net/client/package-info.java new file mode 100644 index 00000000000..e15462e261d --- /dev/null +++ b/src/main/java/forge/net/client/package-info.java @@ -0,0 +1,3 @@ +/** Model (as in model-view-controller) for Forge. */ +package forge.net.client; + diff --git a/src/main/java/forge/net/client/state/ClientState.java b/src/main/java/forge/net/client/state/ClientState.java new file mode 100644 index 00000000000..d546d591c80 --- /dev/null +++ b/src/main/java/forge/net/client/state/ClientState.java @@ -0,0 +1,37 @@ +package forge.net.client.state; + +import forge.net.client.INetClient; +import forge.net.protocol.incoming.EchoPacket; +import forge.net.protocol.incoming.Packet; +import forge.net.protocol.outcoming.EchoMessage; +import forge.net.protocol.outcoming.UnknownPacketMessage; + +/** + * TODO: Write javadoc for this type. + * + */ +public abstract class ClientState implements IClientState { + + private final INetClient client; + + protected ClientState(INetClient client) + { + this.client = client; + } + + @Override + public void onPacket(Packet packet ) { + switch( packet.getOpCode() ) { + case Echo: + EchoPacket p = (EchoPacket)packet; + client.send(new EchoMessage(p.getMessage())); + break; + + default: + client.send(new UnknownPacketMessage()); + break; + + } + } + +} diff --git a/src/main/java/forge/net/client/state/ClientStateUnauthorized.java b/src/main/java/forge/net/client/state/ClientStateUnauthorized.java new file mode 100644 index 00000000000..02c9ab5951e --- /dev/null +++ b/src/main/java/forge/net/client/state/ClientStateUnauthorized.java @@ -0,0 +1,19 @@ +package forge.net.client.state; + +import forge.net.client.INetClient; + +/** + * TODO: Write javadoc for this type. + * + */ +public class ClientStateUnauthorized extends ClientState implements IClientState { + + /** + * TODO: Write javadoc for Constructor. + * @param client + */ + public ClientStateUnauthorized(INetClient client) { + super(client); + } + +} diff --git a/src/main/java/forge/net/client/state/IClientState.java b/src/main/java/forge/net/client/state/IClientState.java new file mode 100644 index 00000000000..ccd0bb5e461 --- /dev/null +++ b/src/main/java/forge/net/client/state/IClientState.java @@ -0,0 +1,11 @@ +package forge.net.client.state; + +import forge.net.protocol.incoming.Packet; + +/** + * TODO: Write javadoc for this type. + * + */ +public interface IClientState { + void onPacket(Packet data); +} diff --git a/src/main/java/forge/net/client/state/package-info.java b/src/main/java/forge/net/client/state/package-info.java new file mode 100644 index 00000000000..ecf84ca4b93 --- /dev/null +++ b/src/main/java/forge/net/client/state/package-info.java @@ -0,0 +1,3 @@ +/** Model (as in model-view-controller) for Forge. */ +package forge.net.client.state; + diff --git a/src/main/java/forge/net/protocol/incoming/ChatPacket.java b/src/main/java/forge/net/protocol/incoming/ChatPacket.java new file mode 100644 index 00000000000..b304d95bf68 --- /dev/null +++ b/src/main/java/forge/net/protocol/incoming/ChatPacket.java @@ -0,0 +1,18 @@ +package forge.net.protocol.incoming; + + +/** + * TODO: Write javadoc for this type. + * + */ +public class ChatPacket extends Packet { + private final String message; + public ChatPacket(String data) { + super(PacketOpcode.Chat); + message = data; + } + public String getMessage() { + return message; + } + +} diff --git a/src/main/java/forge/net/protocol/incoming/EchoPacket.java b/src/main/java/forge/net/protocol/incoming/EchoPacket.java new file mode 100644 index 00000000000..a76f5b73c0a --- /dev/null +++ b/src/main/java/forge/net/protocol/incoming/EchoPacket.java @@ -0,0 +1,19 @@ +package forge.net.protocol.incoming; + + +/** + * TODO: Write javadoc for this type. + * + */ +public class EchoPacket extends Packet { + + private final String message; + public EchoPacket(String data) { + super(PacketOpcode.Echo); + message = data; + } + public String getMessage() { + return message; + } + +} diff --git a/src/main/java/forge/net/protocol/incoming/Packet.java b/src/main/java/forge/net/protocol/incoming/Packet.java new file mode 100644 index 00000000000..cdfcdb67552 --- /dev/null +++ b/src/main/java/forge/net/protocol/incoming/Packet.java @@ -0,0 +1,18 @@ +package forge.net.protocol.incoming; + + +/** + * TODO: Write javadoc for this type. + * + */ +public abstract class Packet { + private final PacketOpcode opCode; + + public Packet(PacketOpcode code) { + opCode = code; + } + + public final PacketOpcode getOpCode() { + return opCode; + } +} diff --git a/src/main/java/forge/net/protocol/incoming/PacketOpcode.java b/src/main/java/forge/net/protocol/incoming/PacketOpcode.java new file mode 100644 index 00000000000..b7eeace6a20 --- /dev/null +++ b/src/main/java/forge/net/protocol/incoming/PacketOpcode.java @@ -0,0 +1,46 @@ +package forge.net.protocol.incoming; + + +/** + * TODO: Write javadoc for this type. + * + */ +public enum PacketOpcode { + Echo("/echo"), + Chat("/s"), + Unknown(""); + + + + private final String opcode; + + private PacketOpcode(String code) { + opcode = code; + } + + /** + * TODO: Write javadoc for this method. + * @param data + * @return + */ + public static Packet decode(String data) { + for(PacketOpcode s : PacketOpcode.values()) { + if ( data.startsWith(s.opcode) ) + return decodePacket(s, data.substring(s.opcode.length()).trim()); + } + if( data.startsWith("/") ) + return new UnknownPacket(data.substring(1)); + else + return new ChatPacket(data); + } + + + private static Packet decodePacket(PacketOpcode code, String data) { + switch(code) { + case Echo: + return new EchoPacket(data); + default: + return new UnknownPacket(data); + } + } +} diff --git a/src/main/java/forge/net/protocol/incoming/UnknownPacket.java b/src/main/java/forge/net/protocol/incoming/UnknownPacket.java new file mode 100644 index 00000000000..9aa5c326aee --- /dev/null +++ b/src/main/java/forge/net/protocol/incoming/UnknownPacket.java @@ -0,0 +1,19 @@ +package forge.net.protocol.incoming; + + +/** + * TODO: Write javadoc for this type. + * + */ +public class UnknownPacket extends Packet { + + private final String message; + public UnknownPacket(String data) { + super(PacketOpcode.Unknown); + message = data; + } + public String getMessage() { + return message; + } + +} diff --git a/src/main/java/forge/net/protocol/incoming/package-info.java b/src/main/java/forge/net/protocol/incoming/package-info.java new file mode 100644 index 00000000000..575936006bb --- /dev/null +++ b/src/main/java/forge/net/protocol/incoming/package-info.java @@ -0,0 +1,3 @@ +/** Model (as in model-view-controller) for Forge. */ +package forge.net.protocol.incoming; + diff --git a/src/main/java/forge/net/protocol/outcoming/EchoMessage.java b/src/main/java/forge/net/protocol/outcoming/EchoMessage.java new file mode 100644 index 00000000000..6fd57b9a9b7 --- /dev/null +++ b/src/main/java/forge/net/protocol/outcoming/EchoMessage.java @@ -0,0 +1,26 @@ +package forge.net.protocol.outcoming; + +/** + * TODO: Write javadoc for this type. + * + */ +public class EchoMessage extends Message { + + private final String message; + + + /** + * TODO: Write javadoc for Constructor. + * @param message2 + */ + public EchoMessage(String message) { + this.message = message; + } + + + @Override + public String toNetString() { + return String.format("System: %s", message); + } + +} diff --git a/src/main/java/forge/net/protocol/outcoming/Message.java b/src/main/java/forge/net/protocol/outcoming/Message.java new file mode 100644 index 00000000000..c5ea23d4016 --- /dev/null +++ b/src/main/java/forge/net/protocol/outcoming/Message.java @@ -0,0 +1,9 @@ +package forge.net.protocol.outcoming; + +/** + * TODO: Write javadoc for this type. + * + */ +public abstract class Message { + public abstract String toNetString(); +} diff --git a/src/main/java/forge/net/protocol/outcoming/UnknownPacketMessage.java b/src/main/java/forge/net/protocol/outcoming/UnknownPacketMessage.java new file mode 100644 index 00000000000..1806206285c --- /dev/null +++ b/src/main/java/forge/net/protocol/outcoming/UnknownPacketMessage.java @@ -0,0 +1,17 @@ +package forge.net.protocol.outcoming; + +/** + * TODO: Write javadoc for this type. + * + */ +public class UnknownPacketMessage extends Message { + + /* (non-Javadoc) + * @see forge.net.protocol.outcoming.Message#toNetString() + */ + @Override + public String toNetString() { + return "Unkown packet received"; + } + +} diff --git a/src/main/java/forge/net/protocol/package-info.java b/src/main/java/forge/net/protocol/package-info.java new file mode 100644 index 00000000000..86423d7b143 --- /dev/null +++ b/src/main/java/forge/net/protocol/package-info.java @@ -0,0 +1,3 @@ +/** Model (as in model-view-controller) for Forge. */ +package forge.net.protocol; +