diff --git a/.gitattributes b/.gitattributes index 75445dba299..bc7415cc0fa 100644 --- a/.gitattributes +++ b/.gitattributes @@ -14316,6 +14316,7 @@ 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/InvalidFieldInPacketException.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/ConnectedClientState.java -text @@ -14331,8 +14332,10 @@ src/main/java/forge/net/protocol/toclient/AuthResultPacketClt.java -text src/main/java/forge/net/protocol/toclient/ChatPacketClt.java -text src/main/java/forge/net/protocol/toclient/EchoPacketClt.java -text src/main/java/forge/net/protocol/toclient/ErrorIncorrectPacketClt.java -text -src/main/java/forge/net/protocol/toclient/ErrorUnknownPacketClt.java -text +src/main/java/forge/net/protocol/toclient/ErrorNoStateForPacketClt.java -text src/main/java/forge/net/protocol/toclient/IPacketClt.java -text +src/main/java/forge/net/protocol/toclient/WelcomePacketClt.java -text +src/main/java/forge/net/protocol/toclient/package-info.java -text src/main/java/forge/net/protocol/toserver/AuthorizePacketSrv.java -text src/main/java/forge/net/protocol/toserver/ChatPacketSrv.java -text src/main/java/forge/net/protocol/toserver/EchoPacketSrv.java -text diff --git a/src/main/java/forge/control/FControl.java b/src/main/java/forge/control/FControl.java index b941f443641..958586e2c6a 100644 --- a/src/main/java/forge/control/FControl.java +++ b/src/main/java/forge/control/FControl.java @@ -322,7 +322,7 @@ public enum FControl { * TODO: Write javadoc for this method. * @return */ - private final NetServer server = new NetServer(81); + private final NetServer server = new NetServer(); public NetServer getServer() { // TODO Auto-generated method stub return server; diff --git a/src/main/java/forge/gui/home/CHomeUI.java b/src/main/java/forge/gui/home/CHomeUI.java index 90957eb698d..4af77ea8559 100644 --- a/src/main/java/forge/gui/home/CHomeUI.java +++ b/src/main/java/forge/gui/home/CHomeUI.java @@ -1,5 +1,7 @@ package forge.gui.home; +import org.apache.commons.lang.StringUtils; + import forge.Command; import forge.Singletons; import forge.control.FControl; @@ -11,6 +13,7 @@ import forge.gui.framework.ICDoc; import forge.gui.home.sanctioned.VSubmenuConstructed; import forge.net.NetServer; import forge.properties.ForgePreferences; +import forge.properties.NewConstants; import forge.properties.ForgePreferences.FPref; /** @@ -81,8 +84,8 @@ public enum CHomeUI implements ICDoc { @Override public void run() { NetServer srv = FControl.SINGLETON_INSTANCE.getServer(); - srv.listen(); - + srv.listen(NewConstants.SERVER_PORT_NUMBER); + VHomeUI.SINGLETON_INSTANCE.getLblStopServer().setEnabled(true); VHomeUI.SINGLETON_INSTANCE.getLblStartServer().setEnabled(false); diff --git a/src/main/java/forge/gui/home/VHomeUI.java b/src/main/java/forge/gui/home/VHomeUI.java index d0d4c9642a9..32c78f0a9f4 100644 --- a/src/main/java/forge/gui/home/VHomeUI.java +++ b/src/main/java/forge/gui/home/VHomeUI.java @@ -59,6 +59,7 @@ import forge.gui.home.variant.VSubmenuPlanechase; import forge.gui.home.variant.VSubmenuVanguard; import forge.gui.toolbox.FLabel; import forge.gui.toolbox.FSkin; +import forge.properties.NewConstants; import forge.properties.ForgePreferences.FPref; import forge.view.FView; @@ -158,7 +159,7 @@ public enum VHomeUI implements IVTopLevelUI { pnlButtons.add(lblExit, "w 110px!, h 30px!, gap 0 10px 0 0"); pnlButtons.add(lblEditor, "w 110px!, h 30px!, sx 2"); - if ( Singletons.getModel().getPreferences().getPrefBoolean(FPref.DEV_MODE_ENABLED) ) { + if ( NewConstants.SERVER_PORT_NUMBER >= 80 ) { pnlButtons.add(lblStartServer, "w 170px!, h 25px!, gap 0 10px 10px 0, sx 2 "); pnlButtons.add(lblStopServer, "w 50px!, h 25px!, gap 0 0 10px 0"); lblStopServer.setEnabled(false); diff --git a/src/main/java/forge/net/NetServer.java b/src/main/java/forge/net/NetServer.java index aede748aee1..cbe5e9d37e7 100644 --- a/src/main/java/forge/net/NetServer.java +++ b/src/main/java/forge/net/NetServer.java @@ -28,16 +28,15 @@ public class NetServer { private final Server srv = new Server(); private final Set _openSockets = new CopyOnWriteArraySet(); - public final int portNumber; + public int portNumber; public final int getPortNumber() { return portNumber; } - public NetServer(int port) { - portNumber = port; + public NetServer() { SelectChannelConnector connector= new SelectChannelConnector(); - connector.setPort(portNumber); + connector.setMaxIdleTime(1200000); // 20 minutes srv.addConnector(connector); ServletContextHandler context = new ServletContextHandler(); @@ -81,7 +80,6 @@ public class NetServer { @Override public void onMessage(String data) { - System.out.println("Received: " + data); _client.onMessage(data); } @@ -92,9 +90,8 @@ public class NetServer { @Override public void onOpen(Connection connection) { _connection = connection; - _client = new NetClient(this); _openSockets.add(this); - send("CardForge server welcomes you."); + _client = new NetClient(this); } @Override @@ -103,14 +100,16 @@ public class NetServer { } } - public void listen() { + public void listen(int port) { if (!srv.isStarted()) { + portNumber = port; URI serverUri = null; try { - srv.start(); Connector connector = srv.getConnectors()[0]; - int port = connector.getLocalPort(); + connector.setPort(portNumber); + srv.start(); + String host = connector.getHost(); serverUri = new URI(String.format("ws://%s:%d/", host == null ? "localhost" : host ,port)); } catch (Exception e) { @@ -127,6 +126,7 @@ public class NetServer { public void stop() { try { srv.stop(); + portNumber = -1; } catch (Exception e) { BugReporter.reportException(e); } diff --git a/src/main/java/forge/net/client/InvalidFieldInPacketException.java b/src/main/java/forge/net/client/InvalidFieldInPacketException.java new file mode 100644 index 00000000000..afd4bc534ac --- /dev/null +++ b/src/main/java/forge/net/client/InvalidFieldInPacketException.java @@ -0,0 +1,29 @@ +package forge.net.client; + +/** + * Indicates incorrect field in an incoming packet + */ +public class InvalidFieldInPacketException extends RuntimeException { + + private static final long serialVersionUID = 4505312413627923468L; + + + /** + * TODO: Write javadoc for Constructor. + * @param message + */ + public InvalidFieldInPacketException(String message) { + super(message); + } + + + /** + * TODO: Write javadoc for Constructor. + * @param message + * @param cause + */ + public InvalidFieldInPacketException(String message, Throwable cause) { + super(message, cause); + } + +} diff --git a/src/main/java/forge/net/client/NetClient.java b/src/main/java/forge/net/client/NetClient.java index 11c8508eb93..5fd81cccc09 100644 --- a/src/main/java/forge/net/client/NetClient.java +++ b/src/main/java/forge/net/client/NetClient.java @@ -12,7 +12,10 @@ import forge.net.client.state.UnauthorizedClientState; import forge.net.client.state.IClientState; import forge.net.protocol.ClientProtocol; import forge.net.protocol.ClientProtocolJson; +import forge.net.protocol.toclient.ErrorIncorrectPacketClt; +import forge.net.protocol.toclient.ErrorNoStateForPacketClt; import forge.net.protocol.toclient.IPacketClt; +import forge.net.protocol.toclient.WelcomePacketClt; import forge.net.protocol.toserver.IPacketSrv; public class NetClient implements IConnectionObserver, INetClient{ @@ -28,6 +31,7 @@ public class NetClient implements IConnectionObserver, INetClient{ state.push(new ConnectedClientState(this)); state.push(new UnauthorizedClientState(this)); protocol = new ClientProtocolJson(); + send(new WelcomePacketClt("Welcome to server")); } public void autorized() { @@ -53,9 +57,15 @@ public class NetClient implements IConnectionObserver, INetClient{ @Override public void onMessage(String data) { IPacketSrv p = protocol.decodePacket(data); - for(IClientState s : state) { - if ( s.processPacket(p) ) - break; + boolean processed = false; + try{ + for(IClientState s : state) { + if ( s.processPacket(p) ) { processed = true; break; } + } + if (!processed) + send(new ErrorNoStateForPacketClt(p.getClass().getSimpleName())); + } catch ( InvalidFieldInPacketException ex ) { + send(new ErrorIncorrectPacketClt(ex.getMessage())); } } diff --git a/src/main/java/forge/net/client/state/ConnectedClientState.java b/src/main/java/forge/net/client/state/ConnectedClientState.java index 38350cdeeb2..eaa7c84710d 100644 --- a/src/main/java/forge/net/client/state/ConnectedClientState.java +++ b/src/main/java/forge/net/client/state/ConnectedClientState.java @@ -3,7 +3,6 @@ package forge.net.client.state; import forge.net.client.INetClient; import forge.net.protocol.toclient.EchoPacketClt; import forge.net.protocol.toclient.ErrorIncorrectPacketClt; -import forge.net.protocol.toclient.ErrorUnknownPacketClt; import forge.net.protocol.toserver.EchoPacketSrv; import forge.net.protocol.toserver.IPacketSrv; import forge.net.protocol.toserver.IncorrectPacketSrv; @@ -28,9 +27,7 @@ public class ConnectedClientState implements IClientState { client.send(new ErrorIncorrectPacketClt(((IncorrectPacketSrv)packet).getMessage())); return true; } - - client.send(new ErrorUnknownPacketClt()); - return true; + return false; } } diff --git a/src/main/java/forge/net/client/state/UnauthorizedClientState.java b/src/main/java/forge/net/client/state/UnauthorizedClientState.java index 25309cd94d8..5cecace8018 100644 --- a/src/main/java/forge/net/client/state/UnauthorizedClientState.java +++ b/src/main/java/forge/net/client/state/UnauthorizedClientState.java @@ -1,6 +1,9 @@ package forge.net.client.state; +import org.apache.commons.lang3.StringUtils; + import forge.net.client.INetClient; +import forge.net.client.InvalidFieldInPacketException; import forge.net.protocol.toclient.AuthResultPacketClt; import forge.net.protocol.toserver.AuthorizePacketSrv; import forge.net.protocol.toserver.IPacketSrv; @@ -25,14 +28,18 @@ public class UnauthorizedClientState implements IClientState { public boolean processPacket(IPacketSrv packet) { if( packet instanceof AuthorizePacketSrv ) { AuthorizePacketSrv p = (AuthorizePacketSrv)packet; - if( true ) { // check credentials here! - client.send(new AuthResultPacketClt(p.getUsername(), true)); - - - client.createPlayer(p.getUsername()); - client.replaceState(this, new InLobbyClientState(client)); - return true; - } + + if( StringUtils.isBlank(p.getUsername())) + throw new InvalidFieldInPacketException("username is blank"); + + // check credentials here! + + client.createPlayer(p.getUsername()); + + client.send(new AuthResultPacketClt(client.getPlayer().getName(), true)); + client.replaceState(this, new InLobbyClientState(client)); + + return true; } return false; diff --git a/src/main/java/forge/net/protocol/ClientProtocolJson.java b/src/main/java/forge/net/protocol/ClientProtocolJson.java index a2befb70745..f4866b20016 100644 --- a/src/main/java/forge/net/protocol/ClientProtocolJson.java +++ b/src/main/java/forge/net/protocol/ClientProtocolJson.java @@ -11,8 +11,9 @@ import forge.net.protocol.toclient.AuthResultPacketClt; import forge.net.protocol.toclient.ChatPacketClt; import forge.net.protocol.toclient.EchoPacketClt; import forge.net.protocol.toclient.ErrorIncorrectPacketClt; -import forge.net.protocol.toclient.ErrorUnknownPacketClt; +import forge.net.protocol.toclient.ErrorNoStateForPacketClt; import forge.net.protocol.toclient.IPacketClt; +import forge.net.protocol.toclient.WelcomePacketClt; import forge.net.protocol.toserver.AuthorizePacketSrv; import forge.net.protocol.toserver.ChatPacketSrv; import forge.net.protocol.toserver.EchoPacketSrv; @@ -37,11 +38,12 @@ public class ClientProtocolJson implements ClientProtocol packetClass = packet.getClass(); String prefix = classToHeaderOutbound.get(packetClass); - return String.format("%s %s", prefix != null ? prefix : "/!unserialized!: " + packetClass.getName(), gson.toJson(packet)); + return String.format("/%s %s", prefix != null ? prefix : "/!unserialized!: " + packetClass.getName(), gson.toJson(packet)); } } diff --git a/src/main/java/forge/net/protocol/toclient/ErrorNoStateForPacketClt.java b/src/main/java/forge/net/protocol/toclient/ErrorNoStateForPacketClt.java new file mode 100644 index 00000000000..8b6b3ec053f --- /dev/null +++ b/src/main/java/forge/net/protocol/toclient/ErrorNoStateForPacketClt.java @@ -0,0 +1,19 @@ +package forge.net.protocol.toclient; + +/** + * TODO: Write javadoc for this type. + * + */ +public class ErrorNoStateForPacketClt implements IPacketClt { + + private final String message; + + public ErrorNoStateForPacketClt(String simpleName) { + message = simpleName; + } + + public String getMessage() { + return message; + } + +} diff --git a/src/main/java/forge/net/protocol/toclient/ErrorUnknownPacketClt.java b/src/main/java/forge/net/protocol/toclient/ErrorUnknownPacketClt.java deleted file mode 100644 index f7a4a9b717e..00000000000 --- a/src/main/java/forge/net/protocol/toclient/ErrorUnknownPacketClt.java +++ /dev/null @@ -1,11 +0,0 @@ -package forge.net.protocol.toclient; - -/** - * TODO: Write javadoc for this type. - * - */ -public class ErrorUnknownPacketClt implements IPacketClt { - - - -} diff --git a/src/main/java/forge/net/protocol/toclient/WelcomePacketClt.java b/src/main/java/forge/net/protocol/toclient/WelcomePacketClt.java new file mode 100644 index 00000000000..af3bde5f20d --- /dev/null +++ b/src/main/java/forge/net/protocol/toclient/WelcomePacketClt.java @@ -0,0 +1,17 @@ +package forge.net.protocol.toclient; + +import forge.model.BuildInfo; + +/** + * TODO: Write javadoc for this type. + * + */ +public class WelcomePacketClt implements IPacketClt { + public final String message; + public final String version; + + public WelcomePacketClt(String welcome) { + message = welcome; + version = BuildInfo.getVersionString(); + } +} diff --git a/src/main/java/forge/net/protocol/toclient/package-info.java b/src/main/java/forge/net/protocol/toclient/package-info.java new file mode 100644 index 00000000000..5fa7f69cdcb --- /dev/null +++ b/src/main/java/forge/net/protocol/toclient/package-info.java @@ -0,0 +1,3 @@ +/** Model (as in model-view-controller) for Forge. */ +package forge.net.protocol.toclient; + diff --git a/src/main/java/forge/properties/ForgeProfileProperties.java b/src/main/java/forge/properties/ForgeProfileProperties.java index 00dbf17b26b..9ac8db50325 100644 --- a/src/main/java/forge/properties/ForgeProfileProperties.java +++ b/src/main/java/forge/properties/ForgeProfileProperties.java @@ -38,11 +38,14 @@ public class ForgeProfileProperties { public final String cacheDir; public final String cardPicsDir; public final Map cardPicsSubDir; + public final int serverPort; private static final String _USER_DIR_KEY = "userDir"; private static final String _CACHE_DIR_KEY = "cacheDir"; private static final String _CARD_PICS_DIR_KEY = "cardPicsDir"; private static final String _CARD_PICS_SUB_DIRS_KEY = "cardPicsSubDirs"; + + private static final String _SERVER_PORT = "serverPort"; public ForgeProfileProperties(String filename) { Properties props = new Properties(); @@ -60,6 +63,8 @@ public class ForgeProfileProperties { cacheDir = _getDir(props, _CACHE_DIR_KEY, defaults.getRight()); cardPicsDir = _getDir(props, _CARD_PICS_DIR_KEY, cacheDir + "pics/cards/"); cardPicsSubDir = _getMap(props, _CARD_PICS_SUB_DIRS_KEY); + serverPort = _getInt(props, _SERVER_PORT, 0); + } @@ -68,6 +73,13 @@ public class ForgeProfileProperties { return FileSection.parseToMap(strMap, "->", "|"); } + private int _getInt(Properties props, String propertyKey, int defaultValue) { + String strValue = props.getProperty(propertyKey, "").trim(); + if ( StringUtils.isNotBlank(strValue) && StringUtils.isNumeric(strValue) ) + return Integer.parseInt(strValue); + return defaultValue; + } + private static String _getDir(Properties props, String propertyKey, String defaultVal) { String retDir = props.getProperty(propertyKey, defaultVal).trim(); if (retDir.isEmpty()) { diff --git a/src/main/java/forge/properties/NewConstants.java b/src/main/java/forge/properties/NewConstants.java index c9bb7dd5fe8..d1a6bd624ed 100644 --- a/src/main/java/forge/properties/NewConstants.java +++ b/src/main/java/forge/properties/NewConstants.java @@ -57,12 +57,14 @@ public final class NewConstants { public static final String CACHE_DIR; public static final String CACHE_CARD_PICS_DIR; public static final Map CACHE_CARD_PICS_SUBDIR; + public static final int SERVER_PORT_NUMBER; static { ForgeProfileProperties profileProps = new ForgeProfileProperties(PROFILE_FILE); USER_DIR = profileProps.userDir; CACHE_DIR = profileProps.cacheDir; CACHE_CARD_PICS_DIR = profileProps.cardPicsDir; CACHE_CARD_PICS_SUBDIR = Collections.unmodifiableMap(profileProps.cardPicsSubDir); + SERVER_PORT_NUMBER = profileProps.serverPort; } // data that is only in the profile dirs