Use MapleClient for session management

First working version of the Netty implementation,
but there's a lot remaining to be done.
This commit is contained in:
P0nk
2021-07-11 18:56:45 +02:00
parent 86224f5152
commit 5a7d8e6b1f
23 changed files with 210 additions and 238 deletions

View File

@@ -92,12 +92,12 @@ public class MapleClient extends ChannelInboundHandlerAdapter {
public static final String CLIENT_REMOTE_ADDRESS = "REMOTE_IP";
private Hwid hwid;
private String remoteHwid; // Mac address + hwid in one. Retrieved from client when attempting to enter game.
private String remoteAddress;
private volatile boolean inTransition;
private MapleAESOFB send;
private MapleAESOFB receive;
private final IoSession session;
private io.netty.channel.Channel ioChannel;
private PacketProcessor packetProcessor;
@@ -148,13 +148,11 @@ public class MapleClient extends ChannelInboundHandlerAdapter {
this.packetProcessor = packetProcessor;
this.world = world;
this.channel = channel;
this.session = null; // TODO remove once the other constructor is removed
}
public MapleClient(MapleAESOFB send, MapleAESOFB receive, IoSession session) {
this.send = send;
this.receive = receive;
this.session = session;
}
@Override
@@ -266,10 +264,6 @@ public class MapleClient extends ChannelInboundHandlerAdapter {
return send;
}
public IoSession getSession() {
return session;
}
public Hwid getHwid() {
return hwid;
}
@@ -278,6 +272,14 @@ public class MapleClient extends ChannelInboundHandlerAdapter {
this.hwid = hwid;
}
public String getRemoteHwid() {
return remoteHwid;
}
public void setRemoteHwid(String remoteHwid) {
this.remoteHwid = remoteHwid;
}
public String getRemoteAddress() {
return remoteAddress;
}
@@ -352,7 +354,7 @@ public class MapleClient extends ChannelInboundHandlerAdapter {
boolean ret = false;
try (Connection con = DatabaseConnection.getConnection();
PreparedStatement ps = con.prepareStatement("SELECT COUNT(*) FROM ipbans WHERE ? LIKE CONCAT(ip, '%')")) {
ps.setString(1, session.getRemoteAddress().toString());
ps.setString(1, remoteAddress);
try (ResultSet rs = ps.executeQuery()) {
rs.next();
if (rs.getInt(1) > 0) {
@@ -576,7 +578,7 @@ public class MapleClient extends ChannelInboundHandlerAdapter {
pinattempt++;
if (pinattempt > 5) {
MapleSessionCoordinator.getInstance().closeSession(session, false);
MapleSessionCoordinator.getInstance().closeSession(this, false);
}
if (pin.equals(other)) {
pinattempt = 0;
@@ -609,7 +611,7 @@ public class MapleClient extends ChannelInboundHandlerAdapter {
picattempt++;
if (picattempt > 5) {
MapleSessionCoordinator.getInstance().closeSession(session, false);
MapleSessionCoordinator.getInstance().closeSession(this, false);
}
if (pic.equals(other)) { // thanks ryantpayton (HeavenClient) for noticing null pics being checked here
picattempt = 0;
@@ -625,7 +627,7 @@ public class MapleClient extends ChannelInboundHandlerAdapter {
loginattempt++;
if (loginattempt > 4) {
loggedIn = false;
MapleSessionCoordinator.getInstance().closeSession(session, false);
MapleSessionCoordinator.getInstance().closeSession(this, false);
return 6; // thanks Survival_Project for finding out an issue with AUTOMATIC_REGISTER here
}
@@ -677,7 +679,7 @@ public class MapleClient extends ChannelInboundHandlerAdapter {
}
if (loginok == 0 || loginok == 4) {
AntiMulticlientResult res = MapleSessionCoordinator.getInstance().attemptLoginSession(session, nibbleHwid, accId, loginok == 4);
AntiMulticlientResult res = MapleSessionCoordinator.getInstance().attemptLoginSession(this, nibbleHwid, accId, loginok == 4);
switch (res) {
case SUCCESS:
@@ -812,7 +814,7 @@ public class MapleClient extends ChannelInboundHandlerAdapter {
public void updateLoginState(int newState) {
// rules out possibility of multiple account entries
if (newState == LOGIN_LOGGEDIN) {
MapleSessionCoordinator.getInstance().updateOnlineClient(session);
MapleSessionCoordinator.getInstance().updateOnlineClient(this);
}
try (Connection con = DatabaseConnection.getConnection();
@@ -1046,18 +1048,14 @@ public class MapleClient extends ChannelInboundHandlerAdapter {
}
}
}
MapleSessionCoordinator.getInstance().closeSession(this, false);
if (!serverTransition && isLoggedIn()) {
MapleSessionCoordinator.getInstance().closeSession(session, false);
updateLoginState(MapleClient.LOGIN_NOTLOGGEDIN);
session.removeAttribute(MapleClient.CLIENT_KEY); // prevents double dcing during login
clear();
} else {
if (session.containsAttribute(MapleClient.CLIENT_KEY)) {
MapleSessionCoordinator.getInstance().closeSession(session, false);
session.removeAttribute(MapleClient.CLIENT_KEY);
}
if (!Server.getInstance().hasCharacteridInTransition(this)) {
updateLoginState(MapleClient.LOGIN_NOTLOGGEDIN);
}
@@ -1154,18 +1152,9 @@ public class MapleClient extends ChannelInboundHandlerAdapter {
lastPong = Server.getInstance().getCurrentTime();
}
@Deprecated(forRemoval = true)
public void testPing(long timeThen) {
try {
if (lastPong < timeThen) {
if (session != null && session.isConnected()) {
MapleSessionCoordinator.getInstance().closeSession(session, false);
updateLoginState(MapleClient.LOGIN_NOTLOGGEDIN);
session.removeAttribute(MapleClient.CLIENT_KEY);
}
}
} catch (NullPointerException e) {
e.printStackTrace();
}
throw new UnsupportedOperationException();
}
public void checkIfIdle(final IdleStateEvent event) {
@@ -1522,7 +1511,7 @@ public class MapleClient extends ChannelInboundHandlerAdapter {
return;
}
String[] socket = Server.getInstance().getInetSocket(this.getSession(), getWorld(), channel);
String[] socket = Server.getInstance().getInetSocket(this, getWorld(), channel);
if (socket == null) {
announce(MaplePacketCreator.serverNotice(1, "Channel " + channel + " is currently disabled. Try another channel."));
announce(MaplePacketCreator.enableActions());
@@ -1619,8 +1608,13 @@ public class MapleClient extends ChannelInboundHandlerAdapter {
announce(MaplePacketCreator.enableCSUse(player));
}
@Deprecated
public String getNibbleHWID() {
return (String) session.getAttribute(MapleClient.CLIENT_NIBBLEHWID);
if (hwid != null) {
return hwid.hwid();
}
return null;
}
public boolean canBypassPin() {
@@ -1638,4 +1632,8 @@ public class MapleClient extends ChannelInboundHandlerAdapter {
public void setLanguage(int lingua) {
this.lang = lingua;
}
public static MapleClient getPlaceholder() {
return null;
}
}

View File

@@ -52,7 +52,7 @@ public class BanCommand extends Command {
MapleCharacter target = c.getChannelServer().getPlayerStorage().getCharacterByName(ign);
if (target != null) {
String readableTargetName = MapleCharacter.makeMapleReadable(target.getName());
String ip = target.getClient().getSession().getRemoteAddress().toString().split(":")[0];
String ip = target.getClient().getRemoteAddress();
//Ban ip
try (Connection con = DatabaseConnection.getConnection()) {
if (ip.matches("/[0-9]{1,3}\\..*")) {

View File

@@ -50,7 +50,7 @@ public class IpListCommand extends Command {
str += "\r\n" + GameConstants.WORLD_NAMES[w.getId()] + "\r\n";
for (MapleCharacter chr : chars) {
str += " " + chr.getName() + " - " + chr.getClient().getSession().getRemoteAddress() + "\r\n";
str += " " + chr.getName() + " - " + chr.getClient().getRemoteAddress() + "\r\n";
}
}
}

View File

@@ -49,7 +49,7 @@ public class WarpWorldCommand extends Command {
byte worldb = Byte.parseByte(params[0]);
if (worldb <= (server.getWorldsSize() - 1)) {
try {
String[] socket = server.getInetSocket(c.getSession(), worldb, c.getChannel());
String[] socket = server.getInetSocket(c, worldb, c.getChannel());
c.getWorldServer().removePlayer(player);
player.getMap().removePlayer(player);//LOL FORGOT THIS ><
player.setSessionTransitionState();

View File

@@ -115,28 +115,29 @@ public class MapleServerHandler extends IoHandlerAdapter {
session.setAttribute(MapleClient.CLIENT_REMOTE_ADDRESS, remoteHost);
if (!Server.getInstance().isOnline()) {
MapleSessionCoordinator.getInstance().closeSession(session, true);
MapleSessionCoordinator.getInstance().closeSession(MapleClient.getPlaceholder(), true);
return;
}
if (!isLoginServerHandler()) {
if (Server.getInstance().getChannel(world, channel) == null) {
MapleSessionCoordinator.getInstance().closeSession(session, true);
return;
}
} else {
if (!MapleSessionCoordinator.getInstance().canStartLoginSession(session)) {
return;
}
FilePrinter.print(FilePrinter.SESSION, "IoSession with " + session.getRemoteAddress() + " opened on " + sdf.format(Calendar.getInstance().getTime()), false);
}
final InitializationVector ivSend = InitializationVector.generateSend();
final InitializationVector ivRecv = InitializationVector.generateReceive();
MapleAESOFB sendCypher = new MapleAESOFB(ivSend, (short) (0xFFFF - ServerConstants.VERSION));
MapleAESOFB recvCypher = new MapleAESOFB(ivRecv, ServerConstants.VERSION);
MapleClient client = new MapleClient(sendCypher, recvCypher, session);
if (!isLoginServerHandler()) {
if (Server.getInstance().getChannel(world, channel) == null) {
MapleSessionCoordinator.getInstance().closeSession(MapleClient.getPlaceholder(), true);
return;
}
} else {
if (!MapleSessionCoordinator.getInstance().canStartLoginSession(client)) {
return;
}
FilePrinter.print(FilePrinter.SESSION, "IoSession with " + session.getRemoteAddress() + " opened on " + sdf.format(Calendar.getInstance().getTime()), false);
}
client.setWorld(world);
client.setChannel(channel);
client.setSessionId(sessionId.getAndIncrement()); // Generates a reasonable session id.
@@ -146,9 +147,9 @@ public class MapleServerHandler extends IoHandlerAdapter {
private void closeMapleSession(IoSession session) {
if (isLoginServerHandler()) {
MapleSessionCoordinator.getInstance().closeLoginSession(session);
MapleSessionCoordinator.getInstance().closeLoginSession(MapleClient.getPlaceholder());
} else {
MapleSessionCoordinator.getInstance().closeSession(session, null);
MapleSessionCoordinator.getInstance().closeSession(MapleClient.getPlaceholder(), null);
}
MapleClient client = (MapleClient) session.getAttribute(MapleClient.CLIENT_KEY);

View File

@@ -46,7 +46,7 @@ public class MaplePacketDecoder extends CumulativeProtocolDecoder {
protected boolean doDecode(IoSession session, IoBuffer in, ProtocolDecoderOutput out) throws Exception {
final MapleClient client = (MapleClient) session.getAttribute(MapleClient.CLIENT_KEY);
if(client == null) {
MapleSessionCoordinator.getInstance().closeSession(session, true);
MapleSessionCoordinator.getInstance().closeSession(MapleClient.getPlaceholder(), true);
return false;
}
@@ -60,7 +60,7 @@ public class MaplePacketDecoder extends CumulativeProtocolDecoder {
if (in.remaining() >= 4 && decoderState.packetlength == -1) {
int packetHeader = in.getInt();
if (!rcvdCrypto.isValidHeader(packetHeader)) {
MapleSessionCoordinator.getInstance().closeSession(session, true);
MapleSessionCoordinator.getInstance().closeSession(MapleClient.getPlaceholder(), true);
return false;
}
decoderState.packetlength = MapleAESOFB.getPacketLength(packetHeader);
@@ -87,7 +87,7 @@ public class MaplePacketDecoder extends CumulativeProtocolDecoder {
System.out.println("UnknownPacket:" + SendTo);
}
} else {
FilePrinter.print(FilePrinter.PACKET_STREAM + MapleSessionCoordinator.getSessionRemoteAddress(session) + ".txt", HexTool.toString(new byte[]{decryptedPacket[0], decryptedPacket[1]}) + "...");
FilePrinter.print(FilePrinter.PACKET_STREAM + ".txt", HexTool.toString(new byte[]{decryptedPacket[0], decryptedPacket[1]}) + "...");
}
}
return true;

View File

@@ -21,19 +21,18 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package net.mina;
import config.YamlConfig;
import client.MapleClient;
import config.YamlConfig;
import constants.net.OpcodeConstants;
import net.server.coordinator.session.MapleSessionCoordinator;
import org.apache.mina.core.buffer.IoBuffer;
import org.apache.mina.core.session.IoSession;
import org.apache.mina.filter.codec.ProtocolEncoder;
import org.apache.mina.filter.codec.ProtocolEncoderOutput;
import tools.MapleAESOFB;
import tools.FilePrinter;
import tools.HexTool;
import tools.MapleAESOFB;
import tools.data.input.ByteArrayByteStream;
import tools.data.input.GenericLittleEndianAccessor;
import tools.FilePrinter;
public class MaplePacketEncoder implements ProtocolEncoder {
@@ -59,7 +58,7 @@ public class MaplePacketEncoder implements ProtocolEncoder {
System.out.println("UnknownPacket:" + RecvTo);
}
} else {
FilePrinter.print(FilePrinter.PACKET_STREAM + MapleSessionCoordinator.getSessionRemoteAddress(session) + ".txt", HexTool.toString(new byte[]{input[0], input[1]}) + " ...");
FilePrinter.print(FilePrinter.PACKET_STREAM + ".txt", HexTool.toString(new byte[]{input[0], input[1]}) + " ...");
}
}

View File

@@ -58,7 +58,6 @@ import org.apache.mina.core.buffer.IoBuffer;
import org.apache.mina.core.buffer.SimpleBufferAllocator;
import org.apache.mina.core.service.IoAcceptor;
import org.apache.mina.core.session.IdleStatus;
import org.apache.mina.core.session.IoSession;
import org.apache.mina.filter.codec.ProtocolCodecFilter;
import org.apache.mina.transport.socket.nio.NioSocketAcceptor;
import org.slf4j.Logger;
@@ -294,8 +293,8 @@ public class Server {
}
}
public String[] getInetSocket(IoSession session, int world, int channel) {
String remoteIp = MapleSessionCoordinator.getSessionRemoteAddress(session);
public String[] getInetSocket(MapleClient client, int world, int channel) {
String remoteIp = client.getRemoteAddress();
String[] hostAddress = getIP(world, channel).split(":");
if (IpAddresses.isLocalAddress(remoteIp)) {
@@ -1792,7 +1791,7 @@ public class Server {
}
private static String getRemoteHost(MapleClient client) {
return MapleSessionCoordinator.getSessionRemoteHost(client.getSession());
return MapleSessionCoordinator.getSessionRemoteHost(client);
}
public void setCharacteridInTransition(MapleClient client, int charId) {
@@ -1894,7 +1893,7 @@ public class Server {
if (c.isLoggedIn()) {
c.disconnect(false, false);
} else {
MapleSessionCoordinator.getInstance().closeSession(c.getSession(), true);
MapleSessionCoordinator.getInstance().closeSession(c, true);
}
}
}

View File

@@ -86,7 +86,7 @@ public final class AdminCommandHandler extends AbstractMaplePacketHandler {
target = c.getChannelServer().getPlayerStorage().getCharacterByName(victim);
if (target != null) {
String readableTargetName = MapleCharacter.makeMapleReadable(target.getName());
String ip = target.getClient().getSession().getRemoteAddress().toString().split(":")[0];
String ip = target.getClient().getRemoteAddress();
reason += readableTargetName + " (IP: " + ip + ")";
if (duration == -1) {
target.ban(description + " " + reason);

View File

@@ -39,7 +39,6 @@ import net.server.guild.MapleGuild;
import net.server.world.MaplePartyCharacter;
import net.server.world.PartyOperation;
import net.server.world.World;
import org.apache.mina.core.session.IoSession;
import scripting.event.EventInstanceManager;
import server.life.MobSkill;
import tools.DatabaseConnection;
@@ -112,11 +111,10 @@ public final class PlayerLoggedinHandler extends AbstractMaplePacketHandler {
}
MapleCharacter player = wserv.getPlayerStorage().getCharacterById(cid);
IoSession session = c.getSession();
String remoteHwid;
if (player == null) {
remoteHwid = MapleSessionCoordinator.getInstance().pickLoginSessionHwid(session);
remoteHwid = MapleSessionCoordinator.getInstance().pickLoginSessionHwid(c);
if (remoteHwid == null) {
c.disconnect(true, false);
return;
@@ -126,10 +124,7 @@ public final class PlayerLoggedinHandler extends AbstractMaplePacketHandler {
remoteHwid = clientHwid == null ? null : clientHwid.hwid();
}
int hwidLen = remoteHwid.length();
session.setAttribute(MapleClient.CLIENT_HWID, remoteHwid);
String nibbleHwid = remoteHwid.substring(hwidLen - 8, hwidLen);
session.setAttribute(MapleClient.CLIENT_NIBBLEHWID, nibbleHwid);
c.setRemoteHwid(remoteHwid);
c.setHwid(new Hwid(remoteHwid));
if (!server.validateCharacteridInTransition(c, cid)) {
@@ -393,7 +388,10 @@ public final class PlayerLoggedinHandler extends AbstractMaplePacketHandler {
if (player.getMap().getHPDec() > 0) player.resetHpDecreaseTask();
player.resetPlayerRates();
if (YamlConfig.config.server.USE_ADD_RATES_BY_LEVEL == true) player.setPlayerRates();
if (YamlConfig.config.server.USE_ADD_RATES_BY_LEVEL) {
player.setPlayerRates();
}
player.setWorldRates();
player.updateCouponRates();

View File

@@ -12,6 +12,10 @@ public record Hwid (String hwid) {
}
public static Hwid fromClientString(String clientString) throws IllegalArgumentException {
if (clientString == null) {
throw new IllegalArgumentException("clientString must not be null");
}
String[] split = clientString.split("_");
if (split.length != 2 || split[1].length() != HWID_LENGTH) {
throw new IllegalArgumentException("Hwid validation failed for hwid: " + clientString);

View File

@@ -24,7 +24,6 @@ import client.MapleClient;
import config.YamlConfig;
import net.server.Server;
import net.server.coordinator.login.LoginStorage;
import org.apache.mina.core.session.IoSession;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import tools.DatabaseConnection;
@@ -62,7 +61,7 @@ public class MapleSessionCoordinator {
private final LoginStorage loginStorage = new LoginStorage();
private final Map<Integer, MapleClient> onlineClients = new HashMap<>(); // Key: account id
private final Set<String> onlineRemoteHwids = new HashSet<>(); // Hwid/nibblehwid
private final Map<String, Set<IoSession>> loginRemoteHosts = new HashMap<>(); // Key: Ip (+ nibblehwid)
private final Map<String, Set<MapleClient>> loginRemoteHosts = new HashMap<>(); // Key: Ip (+ nibblehwid)
private final HostHwidCache hostHwidCache = new HostHwidCache();
private MapleSessionCoordinator() {
@@ -93,30 +92,20 @@ public class MapleSessionCoordinator {
return false;
}
public static String getSessionRemoteAddress(IoSession session) {
return (String) session.getAttribute(MapleClient.CLIENT_REMOTE_ADDRESS);
}
public static String getSessionRemoteHost(IoSession session) {
String nibbleHwid = (String) session.getAttribute(MapleClient.CLIENT_NIBBLEHWID);
public static String getSessionRemoteHost(MapleClient client) {
String nibbleHwid = client.getNibbleHWID();
if (nibbleHwid != null) {
return getSessionRemoteAddress(session) + "-" + nibbleHwid;
return client.getRemoteAddress() + "-" + nibbleHwid;
} else {
return getSessionRemoteAddress(session);
return client.getRemoteAddress();
}
}
private static MapleClient getSessionClient(IoSession session) {
return (MapleClient) session.getAttribute(MapleClient.CLIENT_KEY);
}
/**
* Overwrites any existing online client for the account id, making sure to disconnect it as well.
*/
public void updateOnlineClient(IoSession session) {
MapleClient client = getSessionClient(session);
public void updateOnlineClient(MapleClient client) {
if (client != null) {
int accountId = client.getAccID();
disconnectClientIfOnline(accountId);
@@ -131,12 +120,12 @@ public class MapleSessionCoordinator {
}
}
public boolean canStartLoginSession(IoSession session) {
public boolean canStartLoginSession(MapleClient client) {
if (!YamlConfig.config.server.DETERRED_MULTICLIENT) {
return true;
}
String remoteHost = getSessionRemoteHost(session);
String remoteHost = getSessionRemoteHost(client);
final InitializationResult initResult = sessionInit.initialize(remoteHost);
switch (initResult.getAntiMulticlientResult()) {
case REMOTE_PROCESSING -> {
@@ -155,28 +144,28 @@ public class MapleSessionCoordinator {
return false;
}
addLoginRemoteHostSession(remoteHost, session);
addLoginRemoteHostClient(remoteHost, client);
return true;
} finally {
sessionInit.finalize(remoteHost);
}
}
private void addLoginRemoteHostSession(String remoteHost, IoSession session) {
Set<IoSession> sessions = new HashSet<>(2);
sessions.add(session);
loginRemoteHosts.put(remoteHost, sessions);
private void addLoginRemoteHostClient(String remoteHost, MapleClient client) {
Set<MapleClient> clients = new HashSet<>(2);
clients.add(client);
loginRemoteHosts.put(remoteHost, clients);
}
public void closeLoginSession(IoSession session) {
String remoteHost = getSessionRemoteHost(session);
removeRemoteHostSession(remoteHost, session);
public void closeLoginSession(MapleClient client) {
String remoteHost = getSessionRemoteHost(client);
removeRemoteHostClient(remoteHost, client);
String nibbleHwid = (String) session.removeAttribute(MapleClient.CLIENT_NIBBLEHWID);
Hwid nibbleHwid = client.getHwid();
client.setHwid(null);
if (nibbleHwid != null) {
onlineRemoteHwids.remove(nibbleHwid);
onlineRemoteHwids.remove(nibbleHwid.hwid());
MapleClient client = getSessionClient(session);
if (client != null) {
MapleClient loggedClient = onlineClients.get(client.getAccID());
@@ -188,24 +177,24 @@ public class MapleSessionCoordinator {
}
}
private void removeRemoteHostSession(String remoteHost, IoSession session) {
Set<IoSession> sessions = loginRemoteHosts.get(remoteHost);
if (sessions != null) {
sessions.remove(session);
private void removeRemoteHostClient(String remoteHost, MapleClient client) {
Set<MapleClient> clients = loginRemoteHosts.get(remoteHost);
if (clients != null) {
clients.remove(client);
if (sessions.isEmpty()) {
if (clients.isEmpty()) {
loginRemoteHosts.remove(remoteHost);
}
}
}
public AntiMulticlientResult attemptLoginSession(IoSession session, String nibbleHwid, int accountId, boolean routineCheck) {
public AntiMulticlientResult attemptLoginSession(MapleClient client, String nibbleHwid, int accountId, boolean routineCheck) {
if (!YamlConfig.config.server.DETERRED_MULTICLIENT) {
session.setAttribute(MapleClient.CLIENT_NIBBLEHWID, nibbleHwid);
client.setHwid(new Hwid(nibbleHwid));
return AntiMulticlientResult.SUCCESS;
}
String remoteHost = getSessionRemoteHost(session);
String remoteHost = getSessionRemoteHost(client);
InitializationResult initResult = sessionInit.initialize(remoteHost);
if (initResult != InitializationResult.SUCCESS) {
return initResult.getAntiMulticlientResult();
@@ -222,7 +211,7 @@ public class MapleSessionCoordinator {
return AntiMulticlientResult.REMOTE_REACHED_LIMIT;
}
session.setAttribute(MapleClient.CLIENT_NIBBLEHWID, nibbleHwid);
client.setHwid(new Hwid(nibbleHwid));
onlineRemoteHwids.add(nibbleHwid);
return AntiMulticlientResult.SUCCESS;
@@ -231,11 +220,11 @@ public class MapleSessionCoordinator {
}
}
public AntiMulticlientResult attemptGameSession(IoSession session, int accountId, String remoteHwid) {
final String remoteHost = getSessionRemoteHost(session);
public AntiMulticlientResult attemptGameSession(MapleClient client, int accountId, String remoteHwid) {
final String remoteHost = getSessionRemoteHost(client);
if (!YamlConfig.config.server.DETERRED_MULTICLIENT) {
hostHwidCache.addEntry(remoteHost, remoteHwid);
hostHwidCache.addEntry(getSessionRemoteAddress(session), remoteHwid); // no HWID information on the loggedin newcomer session...
hostHwidCache.addEntry(client.getRemoteAddress(), remoteHwid); // no HWID information on the loggedin newcomer session...
return AntiMulticlientResult.SUCCESS;
}
@@ -245,14 +234,14 @@ public class MapleSessionCoordinator {
}
try {
String nibbleHwid = (String) session.getAttribute(MapleClient.CLIENT_NIBBLEHWID); // thanks Paxum for noticing account stuck after PIC failure
Hwid nibbleHwid = client.getHwid(); // thanks Paxum for noticing account stuck after PIC failure
if (nibbleHwid == null) {
return AntiMulticlientResult.REMOTE_NO_MATCH;
}
onlineRemoteHwids.remove(nibbleHwid);
if (!remoteHwid.endsWith(nibbleHwid)) {
if (!remoteHwid.endsWith(nibbleHwid.hwid())) {
return AntiMulticlientResult.REMOTE_NO_MATCH;
} else if (onlineRemoteHwids.contains(remoteHwid)) {
return AntiMulticlientResult.REMOTE_LOGGEDIN;
@@ -263,7 +252,7 @@ public class MapleSessionCoordinator {
// updated session CLIENT_HWID attribute will be set when the player log in the game
onlineRemoteHwids.add(remoteHwid);
hostHwidCache.addEntry(remoteHost, remoteHwid);
hostHwidCache.addEntry(getSessionRemoteAddress(session), remoteHwid);
hostHwidCache.addEntry(client.getRemoteAddress(), remoteHwid);
associateHwidAccountIfAbsent(remoteHwid, accountId);
return AntiMulticlientResult.SUCCESS;
@@ -290,9 +279,8 @@ public class MapleSessionCoordinator {
}
}
private static MapleClient fetchInTransitionSessionClient(IoSession session) {
String remoteHwid = MapleSessionCoordinator.getInstance().getGameSessionHwid(session);
private static MapleClient fetchInTransitionSessionClient(MapleClient client) {
String remoteHwid = MapleSessionCoordinator.getInstance().getGameSessionHwid(client);
if (remoteHwid == null) { // maybe this session was currently in-transition?
return null;
}
@@ -300,42 +288,46 @@ public class MapleSessionCoordinator {
final int hwidLen = remoteHwid.length();
final boolean isOnlyNibbleHwid = hwidLen <= 8;
if (isOnlyNibbleHwid) {
session.setAttribute(MapleClient.CLIENT_NIBBLEHWID, remoteHwid);
client.setHwid(new Hwid(remoteHwid));
} else {
session.setAttribute(MapleClient.CLIENT_HWID, remoteHwid);
session.setAttribute(MapleClient.CLIENT_NIBBLEHWID, remoteHwid.substring(hwidLen - 8, hwidLen));
client.setRemoteHwid(remoteHwid);
client.setHwid(Hwid.fromClientString(remoteHwid));
}
MapleClient client = new MapleClient(null, null, session);
MapleClient fakeClient = new MapleClient(null, null, null);
Integer chrId = Server.getInstance().freeCharacteridInTransition(client);
if (chrId != null) {
try {
client.setAccID(MapleCharacter.loadCharFromDB(chrId, client, false).getAccountID());
fakeClient.setAccID(MapleCharacter.loadCharFromDB(chrId, client, false).getAccountID());
} catch (SQLException sqle) {
sqle.printStackTrace();
}
}
session.setAttribute(MapleClient.CLIENT_KEY, client);
return client;
return fakeClient;
}
public void closeSession(IoSession session, Boolean immediately) {
MapleClient client = getSessionClient(session);
public void closeSession(MapleClient client, Boolean immediately) {
if (client == null) {
client = fetchInTransitionSessionClient(session);
client = fetchInTransitionSessionClient(client);
}
String hwid = (String) session.removeAttribute(MapleClient.CLIENT_NIBBLEHWID); // making sure to clean up calls to this function on login phase
// TODO: client.setNibbleHwid(null);
onlineRemoteHwids.remove(hwid);
Hwid hwid = client.getHwid();
client.setHwid(null); // making sure to clean up calls to this function on login phase
if (hwid != null) {
onlineRemoteHwids.remove(hwid.hwid());
}
hwid = (String) session.removeAttribute(MapleClient.CLIENT_HWID);
String remoteHwid = client.getRemoteHwid();
client.setRemoteHwid(null);
// TODO: client.setHwid(null);
onlineRemoteHwids.remove(hwid);
if (remoteHwid != null) {
onlineRemoteHwids.remove(remoteHwid);
}
if (client != null) {
final boolean isGameSession = hwid != null;
final boolean isGameSession = hwid != null || remoteHwid != null;
if (isGameSession) {
onlineClients.remove(client.getAccID());
} else {
@@ -347,20 +339,20 @@ public class MapleSessionCoordinator {
}
}
}
if (immediately != null) {
session.close(immediately);
if (immediately != null && immediately) {
client.closeSession();
}
}
public String pickLoginSessionHwid(IoSession session) {
String remoteHost = getSessionRemoteAddress(session);
public String pickLoginSessionHwid(MapleClient client) {
String remoteHost = client.getRemoteAddress();
// thanks BHB, resinate for noticing players from same network not being able to login
return hostHwidCache.removeEntryAndGetItsHwid(remoteHost);
}
public String getGameSessionHwid(IoSession session) {
String remoteHost = getSessionRemoteHost(session);
public String getGameSessionHwid(MapleClient client) {
String remoteHost = getSessionRemoteHost(client);
return hostHwidCache.getEntryHwid(remoteHost);
}
@@ -395,11 +387,11 @@ public class MapleSessionCoordinator {
}
if (!loginRemoteHosts.isEmpty()) {
List<Entry<String, Set<IoSession>>> elist = new ArrayList<>(loginRemoteHosts.entrySet());
List<Entry<String, Set<MapleClient>>> elist = new ArrayList<>(loginRemoteHosts.entrySet());
elist.sort(Entry.comparingByKey());
System.out.println("Current login sessions: ");
for (Entry<String, Set<IoSession>> e : elist) {
for (Entry<String, Set<MapleClient>> e : elist) {
System.out.println(" " + e.getKey() + ", size: " + e.getValue().size());
}
}
@@ -429,12 +421,12 @@ public class MapleSessionCoordinator {
}
if (!loginRemoteHosts.isEmpty()) {
List<Entry<String, Set<IoSession>>> elist = new ArrayList<>(loginRemoteHosts.entrySet());
List<Entry<String, Set<MapleClient>>> elist = new ArrayList<>(loginRemoteHosts.entrySet());
elist.sort((e1, e2) -> e1.getKey().compareTo(e2.getKey()));
str += ("Current login sessions:\r\n");
for (Entry<String, Set<IoSession>> e : elist) {
for (Entry<String, Set<MapleClient>> e : elist) {
str += (" " + e.getKey() + ", IP: " + e.getValue() + "\r\n");
}
}

View File

@@ -57,7 +57,7 @@ public final class AfterLoginHandler extends AbstractMaplePacketHandler {
c.announce(MaplePacketCreator.requestPinAfterFailure());
}
} else if (c2 == 0 && c3 == 5) {
MapleSessionCoordinator.getInstance().closeSession(c.getSession(), null);
MapleSessionCoordinator.getInstance().closeSession(c, null);
c.updateLoginState(MapleClient.LOGIN_NOTLOGGEDIN);
}
}

View File

@@ -22,37 +22,28 @@
package net.server.handlers.login;
import client.MapleClient;
import java.net.InetAddress;
import java.net.UnknownHostException;
import net.AbstractMaplePacketHandler;
import net.server.Server;
import net.server.coordinator.session.Hwid;
import net.server.coordinator.session.MapleSessionCoordinator;
import net.server.coordinator.session.MapleSessionCoordinator.AntiMulticlientResult;
import net.server.world.World;
import org.apache.mina.core.session.IoSession;
import tools.MaplePacketCreator;
import tools.data.input.SeekableLittleEndianAccessor;
import java.net.InetAddress;
import java.net.UnknownHostException;
public final class CharSelectedHandler extends AbstractMaplePacketHandler {
private static int parseAntiMulticlientError(AntiMulticlientResult res) {
switch (res) {
case REMOTE_PROCESSING:
return 10;
case REMOTE_LOGGEDIN:
return 7;
case REMOTE_NO_MATCH:
return 17;
case COORDINATOR_ERROR:
return 8;
default:
return 9;
}
return switch (res) {
case REMOTE_PROCESSING -> 10;
case REMOTE_LOGGEDIN -> 7;
case REMOTE_NO_MATCH -> 17;
case COORDINATOR_ERROR -> 8;
default -> 9;
};
}
@Override
@@ -69,22 +60,21 @@ public final class CharSelectedHandler extends AbstractMaplePacketHandler {
c.updateMacs(macs);
c.updateHwid(hwid);
IoSession session = c.getSession();
AntiMulticlientResult res = MapleSessionCoordinator.getInstance().attemptGameSession(session, c.getAccID(), hwid);
AntiMulticlientResult res = MapleSessionCoordinator.getInstance().attemptGameSession(c, c.getAccID(), hwid);
if (res != AntiMulticlientResult.SUCCESS) {
c.announce(MaplePacketCreator.getAfterLoginError(parseAntiMulticlientError(res)));
return;
}
if (c.hasBannedMac() || c.hasBannedHWID()) {
MapleSessionCoordinator.getInstance().closeSession(session, true);
MapleSessionCoordinator.getInstance().closeSession(c, true);
return;
}
Server server = Server.getInstance();
if(!server.haveCharacterEntry(c.getAccID(), charId)) {
MapleSessionCoordinator.getInstance().closeSession(session, true);
MapleSessionCoordinator.getInstance().closeSession(c, true);
return;
}
@@ -95,7 +85,7 @@ public final class CharSelectedHandler extends AbstractMaplePacketHandler {
return;
}
String[] socket = server.getInetSocket(session, c.getWorld(), c.getChannel());
String[] socket = server.getInetSocket(c, c.getWorld(), c.getChannel());
if(socket == null) {
c.announce(MaplePacketCreator.getAfterLoginError(10));
return;

View File

@@ -1,18 +1,17 @@
package net.server.handlers.login;
import java.net.InetAddress;
import java.net.UnknownHostException;
import client.MapleClient;
import net.AbstractMaplePacketHandler;
import net.server.Server;
import net.server.coordinator.session.Hwid;
import net.server.coordinator.session.MapleSessionCoordinator;
import net.server.coordinator.session.MapleSessionCoordinator.AntiMulticlientResult;
import net.server.world.World;
import org.apache.mina.core.session.IoSession;
import tools.MaplePacketCreator;
import tools.data.input.SeekableLittleEndianAccessor;
import client.MapleClient;
import java.net.InetAddress;
import java.net.UnknownHostException;
public class CharSelectedWithPicHandler extends AbstractMaplePacketHandler {
@@ -50,17 +49,15 @@ public class CharSelectedWithPicHandler extends AbstractMaplePacketHandler {
c.updateMacs(macs);
c.updateHwid(hwid);
IoSession session = c.getSession();
if (c.hasBannedMac() || c.hasBannedHWID()) {
MapleSessionCoordinator.getInstance().closeSession(c.getSession(), true);
MapleSessionCoordinator.getInstance().closeSession(c, true);
return;
}
Server server = Server.getInstance();
if(!server.haveCharacterEntry(c.getAccID(), charId)) {
MapleSessionCoordinator.getInstance().closeSession(c.getSession(), true);
MapleSessionCoordinator.getInstance().closeSession(c, true);
return;
}
@@ -72,13 +69,13 @@ public class CharSelectedWithPicHandler extends AbstractMaplePacketHandler {
return;
}
String[] socket = server.getInetSocket(session, c.getWorld(), c.getChannel());
String[] socket = server.getInetSocket(c, c.getWorld(), c.getChannel());
if(socket == null) {
c.announce(MaplePacketCreator.getAfterLoginError(10));
return;
}
AntiMulticlientResult res = MapleSessionCoordinator.getInstance().attemptGameSession(session, c.getAccID(), hwid);
AntiMulticlientResult res = MapleSessionCoordinator.getInstance().attemptGameSession(c, c.getAccID(), hwid);
if (res != AntiMulticlientResult.SUCCESS) {
c.announce(MaplePacketCreator.getAfterLoginError(parseAntiMulticlientError(res)));
return;

View File

@@ -1,18 +1,17 @@
package net.server.handlers.login;
import java.net.InetAddress;
import java.net.UnknownHostException;
import client.MapleClient;
import net.AbstractMaplePacketHandler;
import net.server.Server;
import net.server.coordinator.session.Hwid;
import net.server.coordinator.session.MapleSessionCoordinator;
import net.server.coordinator.session.MapleSessionCoordinator.AntiMulticlientResult;
import net.server.world.World;
import tools.MaplePacketCreator;
import tools.data.input.SeekableLittleEndianAccessor;
import client.MapleClient;
import net.server.coordinator.session.MapleSessionCoordinator;
import net.server.coordinator.session.MapleSessionCoordinator.AntiMulticlientResult;
import org.apache.mina.core.session.IoSession;
import java.net.InetAddress;
import java.net.UnknownHostException;
public final class RegisterPicHandler extends AbstractMaplePacketHandler {
@@ -51,21 +50,20 @@ public final class RegisterPicHandler extends AbstractMaplePacketHandler {
c.updateMacs(macs);
c.updateHwid(hwid);
IoSession session = c.getSession();
AntiMulticlientResult res = MapleSessionCoordinator.getInstance().attemptGameSession(session, c.getAccID(), hwid);
AntiMulticlientResult res = MapleSessionCoordinator.getInstance().attemptGameSession(c, c.getAccID(), hwid);
if (res != AntiMulticlientResult.SUCCESS) {
c.announce(MaplePacketCreator.getAfterLoginError(parseAntiMulticlientError(res)));
return;
}
if (c.hasBannedMac() || c.hasBannedHWID()) {
MapleSessionCoordinator.getInstance().closeSession(c.getSession(), true);
MapleSessionCoordinator.getInstance().closeSession(c, true);
return;
}
Server server = Server.getInstance();
if(!server.haveCharacterEntry(c.getAccID(), charId)) {
MapleSessionCoordinator.getInstance().closeSession(c.getSession(), true);
MapleSessionCoordinator.getInstance().closeSession(c, true);
return;
}
@@ -80,7 +78,7 @@ public final class RegisterPicHandler extends AbstractMaplePacketHandler {
return;
}
String[] socket = server.getInetSocket(session, c.getWorld(), c.getChannel());
String[] socket = server.getInetSocket(c, c.getWorld(), c.getChannel());
if(socket == null) {
c.announce(MaplePacketCreator.getAfterLoginError(10));
return;
@@ -95,7 +93,7 @@ public final class RegisterPicHandler extends AbstractMaplePacketHandler {
e.printStackTrace();
}
} else {
MapleSessionCoordinator.getInstance().closeSession(c.getSession(), true);
MapleSessionCoordinator.getInstance().closeSession(c, true);
}
}
}

View File

@@ -35,7 +35,7 @@ public final class RegisterPinHandler extends AbstractMaplePacketHandler {
public final void handlePacket(SeekableLittleEndianAccessor slea, MapleClient c) {
byte c2 = slea.readByte();
if (c2 == 0) {
MapleSessionCoordinator.getInstance().closeSession(c.getSession(), null);
MapleSessionCoordinator.getInstance().closeSession(c, null);
c.updateLoginState(MapleClient.LOGIN_NOTLOGGEDIN);
} else {
String pin = slea.readMapleAsciiString();
@@ -43,7 +43,7 @@ public final class RegisterPinHandler extends AbstractMaplePacketHandler {
c.setPin(pin);
c.announce(MaplePacketCreator.pinRegistered());
MapleSessionCoordinator.getInstance().closeSession(c.getSession(), null);
MapleSessionCoordinator.getInstance().closeSession(c, null);
c.updateLoginState(MapleClient.LOGIN_NOTLOGGEDIN);
}
}

View File

@@ -44,7 +44,7 @@ public class SetGenderHandler extends AbstractMaplePacketHandler {
Server.getInstance().registerLoginState(c);
} else {
MapleSessionCoordinator.getInstance().closeSession(c.getSession(), null);
MapleSessionCoordinator.getInstance().closeSession(c, null);
c.updateLoginState(MapleClient.LOGIN_NOTLOGGEDIN);
}
}

View File

@@ -1,19 +1,19 @@
package net.server.handlers.login;
import client.MapleClient;
import java.net.InetAddress;
import java.net.UnknownHostException;
import net.AbstractMaplePacketHandler;
import net.server.Server;
import net.server.coordinator.session.Hwid;
import net.server.coordinator.session.MapleSessionCoordinator;
import net.server.coordinator.session.MapleSessionCoordinator.AntiMulticlientResult;
import net.server.world.World;
import org.apache.mina.core.session.IoSession;
import tools.MaplePacketCreator;
import tools.Randomizer;
import tools.data.input.SeekableLittleEndianAccessor;
import java.net.InetAddress;
import java.net.UnknownHostException;
public final class ViewAllCharRegisterPicHandler extends AbstractMaplePacketHandler {
private static int parseAntiMulticlientError(AntiMulticlientResult res) {
@@ -53,12 +53,11 @@ public final class ViewAllCharRegisterPicHandler extends AbstractMaplePacketHand
c.updateHwid(hwid);
if (c.hasBannedMac() || c.hasBannedHWID()) {
MapleSessionCoordinator.getInstance().closeSession(c.getSession(), true);
MapleSessionCoordinator.getInstance().closeSession(c, true);
return;
}
IoSession session = c.getSession();
AntiMulticlientResult res = MapleSessionCoordinator.getInstance().attemptGameSession(session, c.getAccID(), hwid);
AntiMulticlientResult res = MapleSessionCoordinator.getInstance().attemptGameSession(c, c.getAccID(), hwid);
if (res != AntiMulticlientResult.SUCCESS) {
c.announce(MaplePacketCreator.getAfterLoginError(parseAntiMulticlientError(res)));
return;
@@ -66,7 +65,7 @@ public final class ViewAllCharRegisterPicHandler extends AbstractMaplePacketHand
Server server = Server.getInstance();
if(!server.haveCharacterEntry(c.getAccID(), charId)) {
MapleSessionCoordinator.getInstance().closeSession(c.getSession(), true);
MapleSessionCoordinator.getInstance().closeSession(c, true);
return;
}
@@ -83,7 +82,7 @@ public final class ViewAllCharRegisterPicHandler extends AbstractMaplePacketHand
String pic = slea.readMapleAsciiString();
c.setPic(pic);
String[] socket = server.getInetSocket(session, c.getWorld(), channel);
String[] socket = server.getInetSocket(c, c.getWorld(), channel);
if (socket == null) {
c.announce(MaplePacketCreator.getAfterLoginError(10));
return;

View File

@@ -22,19 +22,19 @@
package net.server.handlers.login;
import client.MapleClient;
import java.net.InetAddress;
import java.net.UnknownHostException;
import net.AbstractMaplePacketHandler;
import net.server.Server;
import net.server.coordinator.session.Hwid;
import net.server.coordinator.session.MapleSessionCoordinator;
import net.server.coordinator.session.MapleSessionCoordinator.AntiMulticlientResult;
import net.server.world.World;
import org.apache.mina.core.session.IoSession;
import tools.MaplePacketCreator;
import tools.Randomizer;
import tools.data.input.SeekableLittleEndianAccessor;
import java.net.InetAddress;
import java.net.UnknownHostException;
public final class ViewAllCharSelectedHandler extends AbstractMaplePacketHandler {
private static int parseAntiMulticlientError(AntiMulticlientResult res) {
@@ -73,12 +73,11 @@ public final class ViewAllCharSelectedHandler extends AbstractMaplePacketHandler
c.updateHwid(hwid);
if (c.hasBannedMac() || c.hasBannedHWID()) {
MapleSessionCoordinator.getInstance().closeSession(c.getSession(), true);
MapleSessionCoordinator.getInstance().closeSession(c, true);
return;
}
IoSession session = c.getSession();
AntiMulticlientResult res = MapleSessionCoordinator.getInstance().attemptGameSession(session, c.getAccID(), hwid);
AntiMulticlientResult res = MapleSessionCoordinator.getInstance().attemptGameSession(c, c.getAccID(), hwid);
if (res != AntiMulticlientResult.SUCCESS) {
c.announce(MaplePacketCreator.getAfterLoginError(parseAntiMulticlientError(res)));
return;
@@ -86,7 +85,7 @@ public final class ViewAllCharSelectedHandler extends AbstractMaplePacketHandler
Server server = Server.getInstance();
if(!server.haveCharacterEntry(c.getAccID(), charId)) {
MapleSessionCoordinator.getInstance().closeSession(c.getSession(), true);
MapleSessionCoordinator.getInstance().closeSession(c, true);
return;
}
@@ -106,7 +105,7 @@ public final class ViewAllCharSelectedHandler extends AbstractMaplePacketHandler
c.setChannel(1);
}
String[] socket = server.getInetSocket(session, c.getWorld(), c.getChannel());
String[] socket = server.getInetSocket(c, c.getWorld(), c.getChannel());
if(socket == null) {
c.announce(MaplePacketCreator.getAfterLoginError(10));
return;

View File

@@ -1,19 +1,18 @@
package net.server.handlers.login;
import java.net.InetAddress;
import java.net.UnknownHostException;
import client.MapleClient;
import net.AbstractMaplePacketHandler;
import net.server.Server;
import net.server.coordinator.session.Hwid;
import net.server.coordinator.session.MapleSessionCoordinator;
import net.server.coordinator.session.MapleSessionCoordinator.AntiMulticlientResult;
import net.server.world.World;
import tools.MaplePacketCreator;
import tools.Randomizer;
import tools.data.input.SeekableLittleEndianAccessor;
import client.MapleClient;
import net.server.coordinator.session.MapleSessionCoordinator;
import net.server.coordinator.session.MapleSessionCoordinator.AntiMulticlientResult;
import org.apache.mina.core.session.IoSession;
import java.net.InetAddress;
import java.net.UnknownHostException;
public class ViewAllCharSelectedWithPicHandler extends AbstractMaplePacketHandler {
@@ -55,15 +54,13 @@ public class ViewAllCharSelectedWithPicHandler extends AbstractMaplePacketHandle
c.updateHwid(hwid);
if (c.hasBannedMac() || c.hasBannedHWID()) {
MapleSessionCoordinator.getInstance().closeSession(c.getSession(), true);
MapleSessionCoordinator.getInstance().closeSession(c, true);
return;
}
IoSession session = c.getSession();
Server server = Server.getInstance();
if(!server.haveCharacterEntry(c.getAccID(), charId)) {
MapleSessionCoordinator.getInstance().closeSession(c.getSession(), true);
MapleSessionCoordinator.getInstance().closeSession(c, true);
return;
}
@@ -78,13 +75,13 @@ public class ViewAllCharSelectedWithPicHandler extends AbstractMaplePacketHandle
c.setChannel(channel);
if (c.checkPic(pic)) {
String[] socket = server.getInetSocket(session, c.getWorld(), c.getChannel());
String[] socket = server.getInetSocket(c, c.getWorld(), c.getChannel());
if(socket == null) {
c.announce(MaplePacketCreator.getAfterLoginError(10));
return;
}
AntiMulticlientResult res = MapleSessionCoordinator.getInstance().attemptGameSession(session, c.getAccID(), hwid);
AntiMulticlientResult res = MapleSessionCoordinator.getInstance().attemptGameSession(c, c.getAccID(), hwid);
if (res != AntiMulticlientResult.SUCCESS) {
c.announce(MaplePacketCreator.getAfterLoginError(parseAntiMulticlientError(res)));
return;

View File

@@ -156,7 +156,7 @@ public class MapleMiniGame extends AbstractMapleMapObject {
public void broadcastToOwner(final byte[] packet) {
MapleClient c = owner.getClient();
if (c != null && c.getSession() != null) {
if (c != null) {
c.announce(packet);
}
}

View File

@@ -386,8 +386,9 @@ public class MaplePlayerShop extends AbstractMapleMapObject {
}
public void broadcast(final byte[] packet) {
if (owner.getClient() != null && owner.getClient().getSession() != null) {
owner.getClient().announce(packet);
MapleClient client = owner.getClient();
if (client != null) {
client.announce(packet);
}
broadcastToVisitors(packet);
}