Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Bukkit thread safety checks and fixes #1992

Open
wants to merge 9 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Cleanup
  • Loading branch information
sgdc3 committed Feb 2, 2020
commit c95443fda7d2ef81493ef0dc672cbf0c16592787
5 changes: 4 additions & 1 deletion src/main/java/fr/xephi/authme/AuthMe.java
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
import fr.xephi.authme.settings.properties.SecuritySettings;
import fr.xephi.authme.task.CleanupTask;
import fr.xephi.authme.task.purge.PurgeService;
import fr.xephi.authme.util.BukkitThreadSafety;
import fr.xephi.authme.util.ExceptionUtils;
import org.bukkit.Server;
import org.bukkit.command.Command;
Expand Down Expand Up @@ -172,7 +173,9 @@ public void onEnable() {
// Successful message
logger.info("AuthMe " + getPluginVersion() + " build n." + getPluginBuildNumber() + " successfully enabled!");
// Start catching wrong sync/async calls
ThreadSafety.setEnabled(true);
if(System.getProperty("authme.disableThreadSafetyChecks") == null) {
BukkitThreadSafety.setEnabled(true);
}

// Purge on start if enabled
PurgeService purgeService = injector.getSingleton(PurgeService.class);
Expand Down
2 changes: 1 addition & 1 deletion src/main/java/fr/xephi/authme/annotation/MightBeAsync.java
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,6 @@
import java.lang.annotation.Target;

@Target({ElementType.METHOD, ElementType.CONSTRUCTOR})
@Retention(RetentionPolicy.RUNTIME)
@Retention(RetentionPolicy.SOURCE)
public @interface MightBeAsync {
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,6 @@
import java.lang.annotation.Target;

@Target({ElementType.METHOD, ElementType.CONSTRUCTOR})
@Retention(RetentionPolicy.RUNTIME)
@Retention(RetentionPolicy.SOURCE)
public @interface ShouldBeAsync {
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
import com.google.common.collect.ImmutableSortedMap;
import fr.xephi.authme.ConsoleLogger;
import fr.xephi.authme.command.ExecutableCommand;
import fr.xephi.authme.datasource.converter.Converter;
import fr.xephi.authme.datasource.converter.AbstractConverter;
import fr.xephi.authme.datasource.converter.CrazyLoginConverter;
import fr.xephi.authme.datasource.converter.LoginSecurityConverter;
import fr.xephi.authme.datasource.converter.MySqlToSqlite;
Expand All @@ -30,7 +30,7 @@
public class ConverterCommand implements ExecutableCommand {

@VisibleForTesting
static final Map<String, Class<? extends Converter>> CONVERTERS = getConverters();
static final Map<String, Class<? extends AbstractConverter>> CONVERTERS = getConverters();

private final ConsoleLogger logger = ConsoleLoggerFactory.get(ConverterCommand.class);

Expand All @@ -41,18 +41,18 @@ public class ConverterCommand implements ExecutableCommand {
private BukkitService bukkitService;

@Inject
private Factory<Converter> converterFactory;
private Factory<AbstractConverter> converterFactory;

@Override
public void executeCommand(CommandSender sender, List<String> arguments) {
Class<? extends Converter> converterClass = getConverterClassFromArgs(arguments);
Class<? extends AbstractConverter> converterClass = getConverterClassFromArgs(arguments);
if (converterClass == null) {
sender.sendMessage("Converters: " + String.join(", ", CONVERTERS.keySet()));
return;
}

// Get the proper converter instance
final Converter converter = converterFactory.newInstance(converterClass);
final AbstractConverter converter = converterFactory.newInstance(converterClass);

// Run the convert job
bukkitService.runTaskAsynchronously(() -> {
Expand All @@ -68,7 +68,7 @@ public void executeCommand(CommandSender sender, List<String> arguments) {
sender.sendMessage("[AuthMe] Successfully started " + arguments.get(0));
}

private static Class<? extends Converter> getConverterClassFromArgs(List<String> arguments) {
private static Class<? extends AbstractConverter> getConverterClassFromArgs(List<String> arguments) {
return arguments.isEmpty()
? null
: CONVERTERS.get(arguments.get(0).toLowerCase());
Expand All @@ -79,8 +79,8 @@ private static Class<? extends Converter> getConverterClassFromArgs(List<String>
*
* @return map with all available converters
*/
private static Map<String, Class<? extends Converter>> getConverters() {
return ImmutableSortedMap.<String, Class<? extends Converter>>naturalOrder()
private static Map<String, Class<? extends AbstractConverter>> getConverters() {
return ImmutableSortedMap.<String, Class<? extends AbstractConverter>>naturalOrder()
.put("xauth", XAuthConverter.class)
.put("crazylogin", CrazyLoginConverter.class)
.put("rakamak", RakamakConverter.class)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
package fr.xephi.authme.command.executable.authme;

import fr.xephi.authme.annotation.MightBeAsync;
import fr.xephi.authme.annotation.ShouldBeAsync;
import fr.xephi.authme.command.ExecutableCommand;
import fr.xephi.authme.datasource.DataSource;
Expand Down
42 changes: 21 additions & 21 deletions src/main/java/fr/xephi/authme/datasource/AbstractSqlDataSource.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
import ch.jalu.datasourcecolumns.data.DataSourceValueImpl;
import ch.jalu.datasourcecolumns.data.DataSourceValues;
import ch.jalu.datasourcecolumns.predicate.AlwaysTruePredicate;
import fr.xephi.authme.ThreadSafety;
import fr.xephi.authme.util.BukkitThreadSafety;
import fr.xephi.authme.annotation.ShouldBeAsync;
import fr.xephi.authme.data.auth.PlayerAuth;
import fr.xephi.authme.datasource.columnshandler.AuthMeColumns;
Expand All @@ -31,7 +31,7 @@ public abstract class AbstractSqlDataSource implements DataSource {
@Override
@ShouldBeAsync
public boolean isAuthAvailable(String user) {
ThreadSafety.shouldBeAsync();
BukkitThreadSafety.shouldBeAsync();
try {
return columnsHandler.retrieve(user, AuthMeColumns.NAME).rowExists();
} catch (SQLException e) {
Expand All @@ -43,7 +43,7 @@ public boolean isAuthAvailable(String user) {
@Override
@ShouldBeAsync
public HashedPassword getPassword(String user) {
ThreadSafety.shouldBeAsync();
BukkitThreadSafety.shouldBeAsync();
try {
DataSourceValues values = columnsHandler.retrieve(user, AuthMeColumns.PASSWORD, AuthMeColumns.SALT);
if (values.rowExists()) {
Expand All @@ -58,7 +58,7 @@ public HashedPassword getPassword(String user) {
@Override
@ShouldBeAsync
public boolean saveAuth(PlayerAuth auth) {
ThreadSafety.shouldBeAsync();
BukkitThreadSafety.shouldBeAsync();
return columnsHandler.insert(auth,
AuthMeColumns.NAME, AuthMeColumns.NICK_NAME, AuthMeColumns.PASSWORD, AuthMeColumns.SALT,
AuthMeColumns.EMAIL, AuthMeColumns.REGISTRATION_DATE, AuthMeColumns.REGISTRATION_IP,
Expand All @@ -68,7 +68,7 @@ public boolean saveAuth(PlayerAuth auth) {
@Override
@ShouldBeAsync
public boolean hasSession(String user) {
ThreadSafety.shouldBeAsync();
BukkitThreadSafety.shouldBeAsync();
try {
DataSourceValue<Integer> result = columnsHandler.retrieve(user, AuthMeColumns.HAS_SESSION);
return result.rowExists() && Integer.valueOf(1).equals(result.getValue());
Expand All @@ -81,21 +81,21 @@ public boolean hasSession(String user) {
@Override
@ShouldBeAsync
public boolean updateSession(PlayerAuth auth) {
ThreadSafety.shouldBeAsync();
BukkitThreadSafety.shouldBeAsync();
return columnsHandler.update(auth, AuthMeColumns.LAST_IP, AuthMeColumns.LAST_LOGIN, AuthMeColumns.NICK_NAME);
}

@Override
@ShouldBeAsync
public boolean updatePassword(PlayerAuth auth) {
ThreadSafety.shouldBeAsync();
BukkitThreadSafety.shouldBeAsync();
return updatePassword(auth.getNickname(), auth.getPassword());
}

@Override
@ShouldBeAsync
public boolean updatePassword(String user, HashedPassword password) {
ThreadSafety.shouldBeAsync();
BukkitThreadSafety.shouldBeAsync();
return columnsHandler.update(user,
with(AuthMeColumns.PASSWORD, password.getHash())
.and(AuthMeColumns.SALT, password.getSalt()).build());
Expand All @@ -104,7 +104,7 @@ public boolean updatePassword(String user, HashedPassword password) {
@Override
@ShouldBeAsync
public boolean updateQuitLoc(PlayerAuth auth) {
ThreadSafety.shouldBeAsync();
BukkitThreadSafety.shouldBeAsync();
return columnsHandler.update(auth,
AuthMeColumns.LOCATION_X, AuthMeColumns.LOCATION_Y, AuthMeColumns.LOCATION_Z,
AuthMeColumns.LOCATION_WORLD, AuthMeColumns.LOCATION_YAW, AuthMeColumns.LOCATION_PITCH);
Expand All @@ -113,7 +113,7 @@ public boolean updateQuitLoc(PlayerAuth auth) {
@Override
@ShouldBeAsync
public List<String> getAllAuthsByIp(String ip) {
ThreadSafety.shouldBeAsync();
BukkitThreadSafety.shouldBeAsync();
try {
return columnsHandler.retrieve(eq(AuthMeColumns.LAST_IP, ip), AuthMeColumns.NAME);
} catch (SQLException e) {
Expand All @@ -125,21 +125,21 @@ public List<String> getAllAuthsByIp(String ip) {
@Override
@ShouldBeAsync
public int countAuthsByEmail(String email) {
ThreadSafety.shouldBeAsync();
BukkitThreadSafety.shouldBeAsync();
return columnsHandler.count(eqIgnoreCase(AuthMeColumns.EMAIL, email));
}

@Override
@ShouldBeAsync
public boolean updateEmail(PlayerAuth auth) {
ThreadSafety.shouldBeAsync();
BukkitThreadSafety.shouldBeAsync();
return columnsHandler.update(auth, AuthMeColumns.EMAIL);
}

@Override
@ShouldBeAsync
public boolean isLogged(String user) {
ThreadSafety.shouldBeAsync();
BukkitThreadSafety.shouldBeAsync();
try {
DataSourceValue<Integer> result = columnsHandler.retrieve(user, AuthMeColumns.IS_LOGGED);
return result.rowExists() && Integer.valueOf(1).equals(result.getValue());
Expand All @@ -152,56 +152,56 @@ public boolean isLogged(String user) {
@Override
@ShouldBeAsync
public void setLogged(String user) {
ThreadSafety.shouldBeAsync();
BukkitThreadSafety.shouldBeAsync();
columnsHandler.update(user, AuthMeColumns.IS_LOGGED, 1);
}

@Override
@ShouldBeAsync
public void setUnlogged(String user) {
ThreadSafety.shouldBeAsync();
BukkitThreadSafety.shouldBeAsync();
columnsHandler.update(user, AuthMeColumns.IS_LOGGED, 0);
}

@Override
@ShouldBeAsync
public void grantSession(String user) {
ThreadSafety.shouldBeAsync();
BukkitThreadSafety.shouldBeAsync();
columnsHandler.update(user, AuthMeColumns.HAS_SESSION, 1);
}

@Override
@ShouldBeAsync
public void revokeSession(String user) {
ThreadSafety.shouldBeAsync();
BukkitThreadSafety.shouldBeAsync();
columnsHandler.update(user, AuthMeColumns.HAS_SESSION, 0);
}

@Override
@ShouldBeAsync
public void purgeLogged() {
ThreadSafety.shouldBeAsync();
BukkitThreadSafety.shouldBeAsync();
columnsHandler.update(eq(AuthMeColumns.IS_LOGGED, 1), AuthMeColumns.IS_LOGGED, 0);
}

@Override
@ShouldBeAsync
public int getAccountsRegistered() {
ThreadSafety.shouldBeAsync();
BukkitThreadSafety.shouldBeAsync();
return columnsHandler.count(new AlwaysTruePredicate<>());
}

@Override
@ShouldBeAsync
public boolean updateRealName(String user, String realName) {
ThreadSafety.shouldBeAsync();
BukkitThreadSafety.shouldBeAsync();
return columnsHandler.update(user, AuthMeColumns.NICK_NAME, realName);
}

@Override
@ShouldBeAsync
public DataSourceValue<String> getEmail(String user) {
ThreadSafety.shouldBeAsync();
BukkitThreadSafety.shouldBeAsync();
try {
return columnsHandler.retrieve(user, AuthMeColumns.EMAIL);
} catch (SQLException e) {
Expand Down
Loading