Added new client-server incompatible checks:

* added strict mode (client and server versions must be same, see MAGE_VERSION_MINOR_PATCH_MUST_BE_SAME);
 * you must enable string mode after github code changes in serializeable classes (see #4459);
 * added client-side version checks;
 * added error message on wrong version disconnects.
This commit is contained in:
Oleg Agafonov 2019-01-18 13:32:37 +04:00
parent fa0e295932
commit f223bdab31
6 changed files with 52 additions and 13 deletions

View file

@ -767,7 +767,7 @@ public class MageFrame extends javax.swing.JFrame implements MageClient {
prepareAndShowTablesPane(); prepareAndShowTablesPane();
return true; return true;
} else { } else {
showMessage("Unable connect to server"); showMessage("Unable connect to server: " + SessionHandler.getLastConnectError());
} }
} finally { } finally {
setCursor(new Cursor(Cursor.DEFAULT_CURSOR)); setCursor(new Cursor(Cursor.DEFAULT_CURSOR));

View file

@ -1,6 +1,5 @@
package mage.client; package mage.client;
import java.util.*;
import mage.cards.decks.DeckCardLists; import mage.cards.decks.DeckCardLists;
import mage.client.chat.LocalCommands; import mage.client.chat.LocalCommands;
import mage.client.dialog.PreferencesDialog; import mage.client.dialog.PreferencesDialog;
@ -16,19 +15,22 @@ import mage.remote.Session;
import mage.remote.SessionImpl; import mage.remote.SessionImpl;
import mage.view.*; import mage.view.*;
import java.util.*;
/** /**
* Created by IGOUDT on 15-9-2016. * Created by IGOUDT on 15-9-2016.
*/ */
public final class SessionHandler { public final class SessionHandler {
private static Session session; private static Session session;
private static String lastConnectError = "";
public static void startSession(MageFrame mageFrame) { public static void startSession(MageFrame mageFrame) {
session = new SessionImpl(mageFrame); session = new SessionImpl(mageFrame);
session.setJsonLogActive("true".equals(PreferencesDialog.getCachedValue(PreferencesDialog.KEY_GAME_LOG_AUTO_SAVE, "true"))); session.setJsonLogActive("true".equals(PreferencesDialog.getCachedValue(PreferencesDialog.KEY_GAME_LOG_AUTO_SAVE, "true")));
} }
public static void ping() { public static void ping() {
session.ping(); session.ping();
} }
@ -46,7 +48,17 @@ public final class SessionHandler {
} }
public static boolean connect(Connection connection) { public static boolean connect(Connection connection) {
return session.connect(connection); lastConnectError = "";
if (session.connect(connection)) {
return true;
} else {
lastConnectError = session.getLastError();
return false;
}
}
public static String getLastConnectError() {
return lastConnectError;
} }
public static boolean stopConnecting() { public static boolean stopConnecting() {

View file

@ -10,6 +10,7 @@ import mage.cards.repository.ExpansionRepository;
import mage.choices.Choice; import mage.choices.Choice;
import mage.choices.ChoiceImpl; import mage.choices.ChoiceImpl;
import mage.client.MageFrame; import mage.client.MageFrame;
import mage.client.SessionHandler;
import mage.client.preference.MagePreferences; import mage.client.preference.MagePreferences;
import mage.client.util.Config; import mage.client.util.Config;
import mage.client.util.gui.countryBox.CountryItemEditor; import mage.client.util.gui.countryBox.CountryItemEditor;
@ -513,7 +514,7 @@ public class ConnectDialog extends MageDialog {
connection.setForceDBComparison(this.chkForceUpdateDB.isSelected() || redownloadDatabase); connection.setForceDBComparison(this.chkForceUpdateDB.isSelected() || redownloadDatabase);
String allMAC = ""; String allMAC = "";
try { try {
allMAC = connection.getMAC(); allMAC = Connection.getMAC();
} catch (SocketException ex) { } catch (SocketException ex) {
} }
connection.setUserIdStr(System.getProperty("user.name") + ":" + System.getProperty("os.name") + ":" + MagePreferences.getUserNames() + ":" + allMAC); connection.setUserIdStr(System.getProperty("user.name") + ":" + System.getProperty("os.name") + ":" + MagePreferences.getUserNames() + ":" + allMAC);
@ -535,6 +536,7 @@ public class ConnectDialog extends MageDialog {
private class ConnectTask extends SwingWorker<Boolean, Void> { private class ConnectTask extends SwingWorker<Boolean, Void> {
private boolean result = false; private boolean result = false;
private String lastConnectError = "";
private static final int CONNECTION_TIMEOUT_MS = 2100; private static final int CONNECTION_TIMEOUT_MS = 2100;
@ -543,6 +545,7 @@ public class ConnectDialog extends MageDialog {
lblStatus.setText("Connecting..."); lblStatus.setText("Connecting...");
btnConnect.setEnabled(false); btnConnect.setEnabled(false);
result = MageFrame.connect(connection); result = MageFrame.connect(connection);
lastConnectError = SessionHandler.getLastConnectError();
return result; return result;
} }
@ -556,7 +559,7 @@ public class ConnectDialog extends MageDialog {
connected(); connected();
MageFrame.getInstance().prepareAndShowTablesPane(); MageFrame.getInstance().prepareAndShowTablesPane();
} else { } else {
lblStatus.setText("Could not connect"); lblStatus.setText("Could not connect: " + lastConnectError);
} }
} catch (InterruptedException ex) { } catch (InterruptedException ex) {
logger.fatal("Update Players Task error", ex); logger.fatal("Update Players Task error", ex);

View file

@ -61,6 +61,7 @@ public class SessionImpl implements Session {
private boolean canceled = false; private boolean canceled = false;
private boolean jsonLogActive = false; private boolean jsonLogActive = false;
private String lastError = "";
static { static {
debugMode = System.getProperty("debug.mage") != null; debugMode = System.getProperty("debug.mage") != null;
@ -195,20 +196,29 @@ public class SessionImpl implements Session {
&& handleRemotingTaskExceptions(new RemotingTask() { && handleRemotingTaskExceptions(new RemotingTask() {
@Override @Override
public boolean run() throws Throwable { public boolean run() throws Throwable {
setLastError("");
logger.info("Trying to log-in as " + getUserName() + " to XMAGE server at " + connection.getHost() + ':' + connection.getPort()); logger.info("Trying to log-in as " + getUserName() + " to XMAGE server at " + connection.getHost() + ':' + connection.getPort());
boolean registerResult; boolean registerResult;
if (connection.getAdminPassword() == null) { if (connection.getAdminPassword() == null) {
// for backward compatibility. don't remove twice call - first one does nothing but for version checking // for backward compatibility. don't remove twice call - first one does nothing but for version checking
registerResult = server.connectUser(connection.getUsername(), connection.getPassword(), sessionId, client.getVersion(), connection.getUserIdStr()); registerResult = server.connectUser(connection.getUsername(), connection.getPassword(), sessionId, client.getVersion(), connection.getUserIdStr());
if (registerResult) {
server.setUserData(connection.getUsername(), sessionId, connection.getUserData(), client.getVersion().toString(), connection.getUserIdStr());
}
} else { } else {
registerResult = server.connectAdmin(connection.getAdminPassword(), sessionId, client.getVersion()); registerResult = server.connectAdmin(connection.getAdminPassword(), sessionId, client.getVersion());
} }
if (registerResult) { if (registerResult) {
serverState = server.getServerState(); serverState = server.getServerState();
// client side check for incompatible versions
if (client.getVersion().compareTo(serverState.getVersion()) != 0) {
String err = "Client and server versions are incompatible.";
setLastError(err);
logger.info(err);
disconnect(false);
return false;
}
if (!connection.getUsername().equals("Admin")) { if (!connection.getUsername().equals("Admin")) {
server.setUserData(connection.getUsername(), sessionId, connection.getUserData(), client.getVersion().toString(), connection.getUserIdStr());
updateDatabase(connection.isForceDBComparison(), serverState); updateDatabase(connection.isForceDBComparison(), serverState);
} }
logger.info("Logged-in as " + getUserName() + " to MAGE server at " + connection.getHost() + ':' + connection.getPort()); logger.info("Logged-in as " + getUserName() + " to MAGE server at " + connection.getHost() + ':' + connection.getPort());
@ -1621,6 +1631,15 @@ public class SessionImpl implements Session {
this.jsonLogActive = jsonLogActive; this.jsonLogActive = jsonLogActive;
} }
private void setLastError(String error) {
lastError = error;
}
@Override
public String getLastError() {
return lastError;
}
} }
class MageAuthenticator extends Authenticator { class MageAuthenticator extends Authenticator {

View file

@ -1,4 +1,3 @@
package mage.remote.interfaces; package mage.remote.interfaces;
import mage.remote.Connection; import mage.remote.Connection;
@ -37,10 +36,12 @@ public interface Connect {
boolean muteUserChat(String userName, long durationMinute); boolean muteUserChat(String userName, long durationMinute);
boolean setActivation(String userName, boolean active); boolean setActivation(String userName, boolean active);
boolean toggleActivation(String userName); boolean toggleActivation(String userName);
boolean lockUser(String userName, long durationMinute); boolean lockUser(String userName, long durationMinute);
String getSessionId(); String getSessionId();
String getLastError();
} }

View file

@ -16,7 +16,9 @@ public class MageVersion implements Serializable, Comparable<MageVersion> {
public final static int MAGE_VERSION_MINOR = 4; public final static int MAGE_VERSION_MINOR = 4;
public final static int MAGE_VERSION_PATCH = 33; public final static int MAGE_VERSION_PATCH = 33;
public final static String MAGE_EDITION_INFO = ""; // set "-beta" for 1.4.32-betaV0 public final static String MAGE_EDITION_INFO = ""; // set "-beta" for 1.4.32-betaV0
public final static String MAGE_VERSION_MINOR_PATCH = "V0"; public final static String MAGE_VERSION_MINOR_PATCH = "V1"; // default V0
// strict mode
private final static boolean MAGE_VERSION_MINOR_PATCH_MUST_BE_SAME = true; // set true on uncompatible github changes, set false after new major release (after MAGE_VERSION_PATCH changes)
private final int major; private final int major;
private final int minor; private final int minor;
@ -74,7 +76,9 @@ public class MageVersion implements Serializable, Comparable<MageVersion> {
if (patch != o.patch) { if (patch != o.patch) {
return patch - o.patch; return patch - o.patch;
} }
if (MAGE_VERSION_MINOR_PATCH_MUST_BE_SAME && !minorPatch.equals(o.minorPatch)) {
return minorPatch.compareTo(o.minorPatch);
}
return editionInfo.compareTo(o.editionInfo); return editionInfo.compareTo(o.editionInfo);
} }
} }