Move session init management to new class
This commit is contained in:
@@ -0,0 +1,20 @@
|
||||
package net.server.coordinator.session;
|
||||
|
||||
import net.server.coordinator.session.MapleSessionCoordinator.AntiMulticlientResult;
|
||||
|
||||
enum InitializationResult {
|
||||
SUCCESS(AntiMulticlientResult.SUCCESS),
|
||||
ALREADY_INITIALIZED(AntiMulticlientResult.REMOTE_PROCESSING),
|
||||
TIMED_OUT(AntiMulticlientResult.COORDINATOR_ERROR),
|
||||
ERROR(AntiMulticlientResult.COORDINATOR_ERROR);
|
||||
|
||||
private final AntiMulticlientResult antiMulticlientResult;
|
||||
|
||||
InitializationResult(AntiMulticlientResult antiMulticlientResult) {
|
||||
this.antiMulticlientResult = antiMulticlientResult;
|
||||
}
|
||||
|
||||
public AntiMulticlientResult getAntiMulticlientResult() {
|
||||
return antiMulticlientResult;
|
||||
}
|
||||
}
|
||||
@@ -23,8 +23,6 @@ import client.MapleCharacter;
|
||||
import client.MapleClient;
|
||||
import config.YamlConfig;
|
||||
import net.server.Server;
|
||||
import net.server.audit.locks.MonitoredLockType;
|
||||
import net.server.audit.locks.factory.MonitoredReentrantLockFactory;
|
||||
import net.server.coordinator.login.LoginStorage;
|
||||
import org.apache.mina.core.session.IoSession;
|
||||
import org.slf4j.Logger;
|
||||
@@ -38,8 +36,6 @@ import java.util.*;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.locks.Lock;
|
||||
import java.util.concurrent.locks.ReentrantLock;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
@@ -63,7 +59,8 @@ public class MapleSessionCoordinator {
|
||||
MANY_ACCOUNT_ATTEMPTS,
|
||||
COORDINATOR_ERROR
|
||||
}
|
||||
|
||||
|
||||
private final SessionInitialization sessionInit = new SessionInitialization();
|
||||
private final LoginStorage loginStorage = new LoginStorage();
|
||||
private final Map<Integer, MapleClient> onlineClients = new HashMap<>();
|
||||
private final Set<String> onlineRemoteHwids = new HashSet<>();
|
||||
@@ -72,12 +69,8 @@ public class MapleSessionCoordinator {
|
||||
|
||||
private final ConcurrentHashMap<String, String> cachedHostHwids = new ConcurrentHashMap<>();
|
||||
private final ConcurrentHashMap<String, Long> cachedHostTimeout = new ConcurrentHashMap<>();
|
||||
private final List<ReentrantLock> poolLock = new ArrayList<>(100);
|
||||
|
||||
private MapleSessionCoordinator() {
|
||||
for(int i = 0; i < 100; i++) {
|
||||
poolLock.add(MonitoredReentrantLockFactory.createLock(MonitoredLockType.SERVER_LOGIN_COORD));
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean attemptAccountAccess(int accountId, String nibbleHwid, boolean routineCheck) {
|
||||
@@ -109,10 +102,6 @@ public class MapleSessionCoordinator {
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private Lock getCoodinatorLock(String remoteHost) {
|
||||
return poolLock.get(Math.abs(remoteHost.hashCode()) % 100);
|
||||
}
|
||||
|
||||
public static String getSessionRemoteAddress(IoSession session) {
|
||||
return (String) session.getAttribute(MapleClient.CLIENT_REMOTE_ADDRESS);
|
||||
@@ -152,9 +141,8 @@ public class MapleSessionCoordinator {
|
||||
}
|
||||
|
||||
String remoteHost = getSessionRemoteHost(session);
|
||||
Lock lock = getCoodinatorLock(remoteHost);
|
||||
AntiMulticlientResult result = addToRemoteHostPoolWithRetries(lock, remoteHost);
|
||||
switch (result) {
|
||||
final InitializationResult initResult = sessionInit.initialize(remoteHost);
|
||||
switch (initResult.getAntiMulticlientResult()) {
|
||||
case REMOTE_PROCESSING -> {
|
||||
return false;
|
||||
}
|
||||
@@ -181,12 +169,7 @@ public class MapleSessionCoordinator {
|
||||
|
||||
return true;
|
||||
} finally {
|
||||
lock.lock();
|
||||
try {
|
||||
pooledRemoteHosts.remove(remoteHost);
|
||||
} finally {
|
||||
lock.unlock();
|
||||
}
|
||||
sessionInit.finalize(remoteHost);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -224,10 +207,9 @@ public class MapleSessionCoordinator {
|
||||
}
|
||||
|
||||
String remoteHost = getSessionRemoteHost(session);
|
||||
final Lock lock = getCoodinatorLock(remoteHost);
|
||||
AntiMulticlientResult hostPoolAdditionResult = addToRemoteHostPoolWithRetries(lock, remoteHost);
|
||||
if (hostPoolAdditionResult != AntiMulticlientResult.SUCCESS) {
|
||||
return hostPoolAdditionResult;
|
||||
InitializationResult initResult = sessionInit.initialize(remoteHost);
|
||||
if (initResult != InitializationResult.SUCCESS) {
|
||||
return initResult.getAntiMulticlientResult();
|
||||
}
|
||||
|
||||
try {
|
||||
@@ -254,12 +236,7 @@ public class MapleSessionCoordinator {
|
||||
|
||||
return AntiMulticlientResult.SUCCESS;
|
||||
} finally {
|
||||
lock.lock();
|
||||
try {
|
||||
pooledRemoteHosts.remove(remoteHost);
|
||||
} finally {
|
||||
lock.unlock();
|
||||
}
|
||||
sessionInit.finalize(remoteHost);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -271,10 +248,9 @@ public class MapleSessionCoordinator {
|
||||
return AntiMulticlientResult.SUCCESS;
|
||||
}
|
||||
|
||||
final Lock lock = getCoodinatorLock(remoteHost);
|
||||
AntiMulticlientResult hostPoolAdditionResult = addToRemoteHostPoolWithRetries(lock, remoteHost);
|
||||
if (hostPoolAdditionResult != AntiMulticlientResult.SUCCESS) {
|
||||
return hostPoolAdditionResult;
|
||||
final InitializationResult initResult = sessionInit.initialize(remoteHost);
|
||||
if (initResult != InitializationResult.SUCCESS) {
|
||||
return initResult.getAntiMulticlientResult();
|
||||
}
|
||||
|
||||
try {
|
||||
@@ -303,48 +279,10 @@ public class MapleSessionCoordinator {
|
||||
|
||||
return AntiMulticlientResult.SUCCESS;
|
||||
} finally {
|
||||
lock.lock();
|
||||
try {
|
||||
pooledRemoteHosts.remove(remoteHost);
|
||||
} finally {
|
||||
lock.unlock();
|
||||
}
|
||||
sessionInit.finalize(remoteHost);
|
||||
}
|
||||
}
|
||||
|
||||
private AntiMulticlientResult addToRemoteHostPoolWithRetries(Lock lock, String remoteHost) {
|
||||
try {
|
||||
int tries = 0;
|
||||
while (true) {
|
||||
if (lock.tryLock()) {
|
||||
try {
|
||||
if (pooledRemoteHosts.contains(remoteHost)) {
|
||||
return AntiMulticlientResult.REMOTE_PROCESSING;
|
||||
}
|
||||
|
||||
pooledRemoteHosts.add(remoteHost);
|
||||
} finally {
|
||||
lock.unlock();
|
||||
}
|
||||
|
||||
break;
|
||||
} else {
|
||||
if(tries == 2) {
|
||||
return AntiMulticlientResult.COORDINATOR_ERROR;
|
||||
}
|
||||
tries++;
|
||||
|
||||
Thread.sleep(1777);
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return AntiMulticlientResult.COORDINATOR_ERROR;
|
||||
}
|
||||
|
||||
return AntiMulticlientResult.SUCCESS;
|
||||
}
|
||||
|
||||
private static void associateHwidAccountIfAbsent(String remoteHwid, int accountId) {
|
||||
try (Connection con = DatabaseConnection.getConnection()) {
|
||||
List<String> hwids = SessionDAO.getHwidsForAccount(con, accountId);
|
||||
|
||||
@@ -0,0 +1,88 @@
|
||||
package net.server.coordinator.session;
|
||||
|
||||
import net.server.audit.locks.MonitoredLockType;
|
||||
import net.server.audit.locks.factory.MonitoredReentrantLockFactory;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.locks.Lock;
|
||||
|
||||
/**
|
||||
* Manages session initialization using remote host (ip address).
|
||||
*/
|
||||
public class SessionInitialization {
|
||||
private final static Logger log = LoggerFactory.getLogger(SessionInitialization.class);
|
||||
private static final int MAX_INIT_TRIES = 2;
|
||||
private static final long RETRY_DELAY_MILLIS = 1777;
|
||||
|
||||
private final Set<String> remoteHostsInInitState = new HashSet<>();
|
||||
private final List<Lock> locks = new ArrayList<>(100);
|
||||
|
||||
SessionInitialization() {
|
||||
for (int i = 0; i < 100; i++) {
|
||||
locks.add(MonitoredReentrantLockFactory.createLock(MonitoredLockType.SERVER_LOGIN_COORD));
|
||||
}
|
||||
}
|
||||
|
||||
private Lock getLock(String remoteHost) {
|
||||
return locks.get(Math.abs(remoteHost.hashCode()) % 100);
|
||||
}
|
||||
|
||||
/**
|
||||
* Try to initialize a session. Should be called <em>before</em> any session initialization procedure.
|
||||
*
|
||||
* @return InitializationResult.SUCCESS if initialization was successful.
|
||||
* If it was successful, finalize() needs to be called shortly after,
|
||||
* or else the initialization will be left hanging in a bad state,
|
||||
* which means any subsequent initialization from the same remote host will fail.
|
||||
*/
|
||||
public InitializationResult initialize(String remoteHost) {
|
||||
final Lock lock = getLock(remoteHost);
|
||||
try {
|
||||
int tries = 0;
|
||||
while (true) {
|
||||
if (lock.tryLock()) {
|
||||
try {
|
||||
if (remoteHostsInInitState.contains(remoteHost)) {
|
||||
return InitializationResult.ALREADY_INITIALIZED;
|
||||
}
|
||||
|
||||
remoteHostsInInitState.add(remoteHost);
|
||||
} finally {
|
||||
lock.unlock();
|
||||
}
|
||||
|
||||
break;
|
||||
} else {
|
||||
if (tries++ == MAX_INIT_TRIES) {
|
||||
return InitializationResult.TIMED_OUT;
|
||||
}
|
||||
|
||||
Thread.sleep(RETRY_DELAY_MILLIS);
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.error("Failed to initialize session.", e);
|
||||
return InitializationResult.ERROR;
|
||||
}
|
||||
|
||||
return InitializationResult.SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* Finalize an initialization. Should be called <em>after</em> any session initialization procedure.
|
||||
*/
|
||||
public void finalize(String remoteHost) {
|
||||
final Lock lock = getLock(remoteHost);
|
||||
lock.lock();
|
||||
try {
|
||||
remoteHostsInInitState.remove(remoteHost);
|
||||
} finally {
|
||||
lock.unlock();
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user