Disconnect client by throwing exception in handler
This makes it easier to add checks in handlers, which should improve security over time. I think this approach is more readable and testable than calling Client#disconnect straight up, while it also decentralizes the handling.
This commit is contained in:
@@ -29,6 +29,8 @@ import io.netty.channel.ChannelInboundHandlerAdapter;
|
||||
import io.netty.handler.timeout.IdleStateEvent;
|
||||
import net.PacketHandler;
|
||||
import net.PacketProcessor;
|
||||
import net.netty.DisconnectException;
|
||||
import net.netty.GameViolationException;
|
||||
import net.netty.InvalidPacketHeaderException;
|
||||
import net.packet.InPacket;
|
||||
import net.packet.Packet;
|
||||
@@ -201,6 +203,8 @@ public class Client extends ChannelInboundHandlerAdapter {
|
||||
try {
|
||||
MonitoredChrLogger.logPacketIfMonitored(this, opcode, packet.getBytes());
|
||||
handler.handlePacket(packet, this);
|
||||
} catch (GameViolationException gve) {
|
||||
throw new DisconnectException(this, gve.getMessage());
|
||||
} catch (final Throwable t) {
|
||||
final String chrInfo = player != null ? player.getName() + " on map " + player.getMapId() : "?";
|
||||
log.warn("Error in packet handler {}. Chr {}, account {}. Packet: {}", handler.getClass().getSimpleName(),
|
||||
@@ -229,6 +233,8 @@ public class Client extends ChannelInboundHandlerAdapter {
|
||||
SessionCoordinator.getInstance().closeSession(this, true);
|
||||
} else if (cause instanceof IOException) {
|
||||
closeMapleSession();
|
||||
} else {
|
||||
ctx.fireExceptionCaught(cause);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1018,7 +1024,7 @@ public class Client extends ChannelInboundHandlerAdapter {
|
||||
//getChannelServer().removePlayer(player); already being done
|
||||
|
||||
player.cancelAllDebuffs();
|
||||
player.saveCharToDB(true);
|
||||
player.saveCharToDB();
|
||||
|
||||
player.logOff();
|
||||
if (YamlConfig.config.server.INSTANT_NAME_CHANGE) {
|
||||
|
||||
@@ -35,6 +35,7 @@ import client.inventory.manipulator.KarmaManipulator;
|
||||
import config.YamlConfig;
|
||||
import constants.id.ItemId;
|
||||
import constants.inventory.ItemConstants;
|
||||
import net.netty.GameViolationException;
|
||||
import net.server.channel.Channel;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
@@ -296,24 +297,22 @@ public class DueyProcessor {
|
||||
if (sendMessage != null && sendMessage.length() > 100) {
|
||||
AutobanFactory.PACKET_EDIT.alert(c.getPlayer(), c.getPlayer().getName() + " tried to packet edit with Quick Delivery on duey.");
|
||||
log.warn("Chr {} tried to use duey with too long of a text", c.getPlayer().getName());
|
||||
c.disconnect(true, false);
|
||||
return;
|
||||
throw GameViolationException.textLength(sendMessage);
|
||||
}
|
||||
|
||||
if (!quick) {
|
||||
fee += 5000;
|
||||
} else if (!c.getPlayer().haveItem(ItemId.QUICK_DELIVERY_TICKET)) {
|
||||
AutobanFactory.PACKET_EDIT.alert(c.getPlayer(), c.getPlayer().getName() + " tried to packet edit with Quick Delivery on duey.");
|
||||
log.warn("Chr {} tried to use duey with Quick Delivery without a ticket, mesos {} and amount {}", c.getPlayer().getName(), sendMesos, amount);
|
||||
c.disconnect(true, false);
|
||||
return;
|
||||
throw new GameViolationException("Send Duey quick delivery without having a ticket");
|
||||
}
|
||||
|
||||
long finalcost = (long) sendMesos + fee;
|
||||
if (finalcost < 0 || finalcost > Integer.MAX_VALUE || (amount < 1 && sendMesos == 0)) {
|
||||
AutobanFactory.PACKET_EDIT.alert(c.getPlayer(), c.getPlayer().getName() + " tried to packet edit with duey.");
|
||||
log.warn("Chr {} tried to use duey with mesos {} and amount {}", c.getPlayer().getName(), sendMesos, amount);
|
||||
c.disconnect(true, false);
|
||||
return;
|
||||
throw new GameViolationException("Send invalid mesos with duey");
|
||||
}
|
||||
|
||||
if(c.getPlayer().getMeso() < finalcost) {
|
||||
|
||||
@@ -32,6 +32,7 @@ import client.inventory.manipulator.KarmaManipulator;
|
||||
import config.YamlConfig;
|
||||
import constants.id.ItemId;
|
||||
import constants.inventory.ItemConstants;
|
||||
import net.netty.GameViolationException;
|
||||
import net.packet.InPacket;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
@@ -69,8 +70,7 @@ public class StorageProcessor {
|
||||
if (slot < 0 || slot > storage.getSlots()) { // removal starts at zero
|
||||
AutobanFactory.PACKET_EDIT.alert(c.getPlayer(), c.getPlayer().getName() + " tried to packet edit with storage.");
|
||||
log.warn("Chr {} tried to work with storage slot {}", c.getPlayer().getName(), slot);
|
||||
c.disconnect(true, false);
|
||||
return;
|
||||
throw new GameViolationException("Withdraw item from invalid slot");
|
||||
}
|
||||
|
||||
slot = storage.getSlot(InventoryType.getByType(type), slot);
|
||||
@@ -128,8 +128,7 @@ public class StorageProcessor {
|
||||
AutobanFactory.PACKET_EDIT.alert(c.getPlayer(),
|
||||
c.getPlayer().getName() + " tried to packet edit with storage.");
|
||||
log.warn("Chr {} tried to store item at slot {}", c.getPlayer().getName(), slot);
|
||||
c.disconnect(true, false);
|
||||
return;
|
||||
throw new GameViolationException("Store item at invalid slot");
|
||||
}
|
||||
|
||||
if (hasGMRestrictions(chr)) {
|
||||
|
||||
@@ -31,6 +31,7 @@ import client.inventory.InventoryType;
|
||||
import client.inventory.Item;
|
||||
import config.YamlConfig;
|
||||
import constants.skills.*;
|
||||
import net.netty.GameViolationException;
|
||||
import net.packet.InPacket;
|
||||
import tools.PacketCreator;
|
||||
import tools.Randomizer;
|
||||
@@ -385,9 +386,7 @@ public class AssignAPProcessor {
|
||||
} else {
|
||||
if (inPacket.available() < 16) {
|
||||
AutobanFactory.PACKET_EDIT.alert(chr, "Didn't send full packet for Auto Assign.");
|
||||
|
||||
c.disconnect(true, false);
|
||||
return;
|
||||
throw new GameViolationException("Auto Assign packet is too small");
|
||||
}
|
||||
|
||||
for (int i = 0; i < 2; i++) {
|
||||
|
||||
@@ -30,6 +30,7 @@ import client.SkillFactory;
|
||||
import client.autoban.AutobanFactory;
|
||||
import constants.game.GameConstants;
|
||||
import constants.skills.Aran;
|
||||
import net.netty.GameViolationException;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import tools.PacketCreator;
|
||||
@@ -50,9 +51,7 @@ public class AssignSPProcessor {
|
||||
if ((!GameConstants.isPqSkillMap(player.getMapId()) && GameConstants.isPqSkill(skillid)) || (!player.isGM() && GameConstants.isGMSkills(skillid)) || (!GameConstants.isInJobTree(skillid, player.getJob().getId()) && !player.isGM())) {
|
||||
AutobanFactory.PACKET_EDIT.alert(player, "tried to packet edit in distributing sp.");
|
||||
log.warn("Chr {} tried to use skill {} without it being in their job.", c.getPlayer().getName(), skillid);
|
||||
|
||||
c.disconnect(true, false);
|
||||
return false;
|
||||
throw new GameViolationException("Assign SP into invalid skill");
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package net.netty;
|
||||
|
||||
import database.character.CharacterSaver;
|
||||
import io.netty.bootstrap.ServerBootstrap;
|
||||
import io.netty.channel.Channel;
|
||||
import io.netty.channel.EventLoopGroup;
|
||||
@@ -9,12 +10,14 @@ import io.netty.channel.socket.nio.NioServerSocketChannel;
|
||||
public class ChannelServer extends AbstractServer {
|
||||
private final int world;
|
||||
private final int channel;
|
||||
private final CharacterSaver characterSaver;
|
||||
private Channel nettyChannel;
|
||||
|
||||
public ChannelServer(int port, int world, int channel) {
|
||||
public ChannelServer(int port, int world, int channel, CharacterSaver characterSaver) {
|
||||
super(port);
|
||||
this.world = world;
|
||||
this.channel = channel;
|
||||
this.characterSaver = characterSaver;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -24,7 +27,7 @@ public class ChannelServer extends AbstractServer {
|
||||
ServerBootstrap bootstrap = new ServerBootstrap()
|
||||
.group(parentGroup, childGroup)
|
||||
.channel(NioServerSocketChannel.class)
|
||||
.childHandler(new ChannelServerInitializer(world, channel));
|
||||
.childHandler(new ChannelServerInitializer(world, channel, characterSaver));
|
||||
|
||||
this.nettyChannel = bootstrap.bind(port).syncUninterruptibly().channel();
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package net.netty;
|
||||
|
||||
import client.Client;
|
||||
import database.character.CharacterSaver;
|
||||
import io.netty.channel.socket.SocketChannel;
|
||||
import net.PacketProcessor;
|
||||
import net.server.Server;
|
||||
@@ -14,7 +15,8 @@ public class ChannelServerInitializer extends ServerChannelInitializer {
|
||||
private final int world;
|
||||
private final int channel;
|
||||
|
||||
public ChannelServerInitializer(int world, int channel) {
|
||||
public ChannelServerInitializer(int world, int channel, CharacterSaver characterSaver) {
|
||||
super(characterSaver);
|
||||
this.world = world;
|
||||
this.channel = channel;
|
||||
}
|
||||
|
||||
16
src/main/java/net/netty/DisconnectException.java
Normal file
16
src/main/java/net/netty/DisconnectException.java
Normal file
@@ -0,0 +1,16 @@
|
||||
package net.netty;
|
||||
|
||||
import client.Client;
|
||||
|
||||
public class DisconnectException extends RuntimeException {
|
||||
private final Client client;
|
||||
|
||||
public DisconnectException(Client client, String message) {
|
||||
super(message);
|
||||
this.client = client;
|
||||
}
|
||||
|
||||
public Client getClient() {
|
||||
return client;
|
||||
}
|
||||
}
|
||||
26
src/main/java/net/netty/DisconnectHandler.java
Normal file
26
src/main/java/net/netty/DisconnectHandler.java
Normal file
@@ -0,0 +1,26 @@
|
||||
package net.netty;
|
||||
|
||||
import database.character.CharacterSaver;
|
||||
import io.netty.channel.ChannelHandler.Sharable;
|
||||
import io.netty.channel.ChannelHandlerContext;
|
||||
import io.netty.channel.ChannelInboundHandlerAdapter;
|
||||
|
||||
@Sharable
|
||||
public class DisconnectHandler extends ChannelInboundHandlerAdapter {
|
||||
private final CharacterSaver characterSaver;
|
||||
|
||||
public DisconnectHandler(CharacterSaver characterSaver) {
|
||||
this.characterSaver = characterSaver;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
|
||||
if (cause instanceof DisconnectException de) {
|
||||
var client = de.getClient();
|
||||
client.disconnect(true, false);
|
||||
} else {
|
||||
ctx.fireExceptionCaught(cause);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
17
src/main/java/net/netty/GameViolationException.java
Normal file
17
src/main/java/net/netty/GameViolationException.java
Normal file
@@ -0,0 +1,17 @@
|
||||
package net.netty;
|
||||
|
||||
public class GameViolationException extends RuntimeException {
|
||||
|
||||
public GameViolationException(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
public static GameViolationException inventoryType(int type) {
|
||||
return new GameViolationException("Invalid inventory type: " + type);
|
||||
}
|
||||
|
||||
public static GameViolationException textLength(String text) {
|
||||
int length = text != null ? text.length() : 0;
|
||||
return new GameViolationException("Text too long: " + length);
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,6 @@
|
||||
package net.netty;
|
||||
|
||||
import database.character.CharacterSaver;
|
||||
import io.netty.bootstrap.ServerBootstrap;
|
||||
import io.netty.channel.Channel;
|
||||
import io.netty.channel.EventLoopGroup;
|
||||
@@ -9,10 +10,13 @@ import io.netty.channel.socket.nio.NioServerSocketChannel;
|
||||
public class LoginServer extends AbstractServer {
|
||||
public static final int WORLD_ID = -1;
|
||||
public static final int CHANNEL_ID = -1;
|
||||
|
||||
private final CharacterSaver characterSaver;
|
||||
private Channel channel;
|
||||
|
||||
public LoginServer(int port) {
|
||||
public LoginServer(int port, CharacterSaver characterSaver) {
|
||||
super(port);
|
||||
this.characterSaver = characterSaver;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -22,7 +26,7 @@ public class LoginServer extends AbstractServer {
|
||||
ServerBootstrap bootstrap = new ServerBootstrap()
|
||||
.group(parentGroup, childGroup)
|
||||
.channel(NioServerSocketChannel.class)
|
||||
.childHandler(new LoginServerInitializer());
|
||||
.childHandler(new LoginServerInitializer(characterSaver));
|
||||
|
||||
this.channel = bootstrap.bind(port).syncUninterruptibly().channel();
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package net.netty;
|
||||
|
||||
import client.Client;
|
||||
import database.character.CharacterSaver;
|
||||
import io.netty.channel.socket.SocketChannel;
|
||||
import net.PacketProcessor;
|
||||
import net.server.coordinator.session.SessionCoordinator;
|
||||
@@ -10,6 +11,10 @@ import org.slf4j.LoggerFactory;
|
||||
public class LoginServerInitializer extends ServerChannelInitializer {
|
||||
private static final Logger log = LoggerFactory.getLogger(LoginServerInitializer.class);
|
||||
|
||||
public LoginServerInitializer(CharacterSaver characterSaver) {
|
||||
super(characterSaver);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initChannel(SocketChannel socketChannel) {
|
||||
final String clientIp = socketChannel.remoteAddress().getHostString();
|
||||
|
||||
@@ -3,6 +3,7 @@ package net.netty;
|
||||
import client.Client;
|
||||
import config.YamlConfig;
|
||||
import constants.net.ServerConstants;
|
||||
import database.character.CharacterSaver;
|
||||
import io.netty.buffer.Unpooled;
|
||||
import io.netty.channel.Channel;
|
||||
import io.netty.channel.ChannelHandler;
|
||||
@@ -30,8 +31,14 @@ public abstract class ServerChannelInitializer extends ChannelInitializer<Socket
|
||||
private static final ChannelHandler sendPacketLogger = new OutPacketLogger();
|
||||
private static final ChannelHandler receivePacketLogger = new InPacketLogger();
|
||||
|
||||
private final DisconnectHandler disconnectingInboundHandler;
|
||||
|
||||
static final AtomicLong sessionId = new AtomicLong(7777);
|
||||
|
||||
public ServerChannelInitializer(CharacterSaver characterSaver) {
|
||||
this.disconnectingInboundHandler = new DisconnectHandler(characterSaver);
|
||||
}
|
||||
|
||||
String getRemoteAddress(Channel channel) {
|
||||
String remoteAddress = "null";
|
||||
try {
|
||||
@@ -62,6 +69,7 @@ public abstract class ServerChannelInitializer extends ChannelInitializer<Socket
|
||||
pipeline.addLast("IdleStateHandler", new IdleStateHandler(0, 0, IDLE_TIME_SECONDS));
|
||||
pipeline.addLast("PacketCodec", new PacketCodec(ClientCyphers.of(sendIv, recvIv)));
|
||||
pipeline.addLast("Client", client);
|
||||
pipeline.addLast("Disconnect", disconnectingInboundHandler);
|
||||
|
||||
if (LOG_PACKETS) {
|
||||
pipeline.addBefore("Client", "SendPacketLogger", sendPacketLogger);
|
||||
|
||||
@@ -367,7 +367,7 @@ public class Server {
|
||||
wldRLock.unlock();
|
||||
}
|
||||
|
||||
Channel channel = new Channel(worldid, channelid, getCurrentTime(), channelDependencies.dropProvider());
|
||||
Channel channel = new Channel(worldid, channelid, getCurrentTime(), channelDependencies);
|
||||
channel.setServerMessage(YamlConfig.config.worlds.get(worldid).why_am_i_recommended);
|
||||
|
||||
if (world.addChannel(channel)) {
|
||||
@@ -440,7 +440,7 @@ public class Server {
|
||||
long bootTime = getCurrentTime();
|
||||
for (int j = 1; j <= YamlConfig.config.worlds.get(i).channels; j++) {
|
||||
int channelid = j;
|
||||
Channel channel = new Channel(i, channelid, bootTime, channelDependencies.dropProvider());
|
||||
Channel channel = new Channel(i, channelid, bootTime, channelDependencies);
|
||||
|
||||
world.addChannel(channel);
|
||||
channelInfo.put(channelid, channel.getIP());
|
||||
@@ -928,7 +928,7 @@ public class Server {
|
||||
}
|
||||
}
|
||||
|
||||
loginServer = initLoginServer(8484);
|
||||
loginServer = initLoginServer(8484, channelDependencies.characterSaver());
|
||||
|
||||
log.info("Listening on port 8484");
|
||||
|
||||
@@ -999,8 +999,8 @@ public class Server {
|
||||
return channelDependencies;
|
||||
}
|
||||
|
||||
private LoginServer initLoginServer(int port) {
|
||||
LoginServer loginServer = new LoginServer(port);
|
||||
private LoginServer initLoginServer(int port, CharacterSaver characterSaver) {
|
||||
LoginServer loginServer = new LoginServer(port, characterSaver);
|
||||
loginServer.start();
|
||||
return loginServer;
|
||||
}
|
||||
|
||||
@@ -24,7 +24,9 @@ package net.server.channel;
|
||||
import client.Character;
|
||||
import config.YamlConfig;
|
||||
import constants.id.MapId;
|
||||
import database.character.CharacterSaver;
|
||||
import database.drop.DropProvider;
|
||||
import net.ChannelDependencies;
|
||||
import net.netty.ChannelServer;
|
||||
import net.packet.Packet;
|
||||
import net.server.PlayerStorage;
|
||||
@@ -109,10 +111,10 @@ public final class Channel {
|
||||
private final Lock merchRlock;
|
||||
private final Lock merchWlock;
|
||||
|
||||
public Channel(final int world, final int channel, long startTime, DropProvider dropProvider) {
|
||||
public Channel(final int world, final int channel, long startTime, ChannelDependencies channelDependencies) {
|
||||
this.world = world;
|
||||
this.channel = channel;
|
||||
this.dropProvider = dropProvider;
|
||||
this.dropProvider = channelDependencies.dropProvider();
|
||||
|
||||
this.ongoingStartTime = startTime + 10000; // rude approach to a world's last channel boot time, placeholder for the 1st wedding reservation ever
|
||||
this.mapManager = new MapManager(null, world, channel, dropProvider);
|
||||
@@ -124,7 +126,7 @@ public final class Channel {
|
||||
this.merchWlock = rwLock.writeLock();
|
||||
|
||||
try {
|
||||
this.channelServer = initServer(port, world, channel);
|
||||
this.channelServer = initServer(port, world, channel, channelDependencies.characterSaver());
|
||||
expedType.addAll(Arrays.asList(ExpeditionType.values()));
|
||||
|
||||
if (Server.getInstance().isOnline()) { // postpone event loading to improve boot time... thanks Riizade, daronhudson for noticing slow startup times
|
||||
@@ -152,8 +154,8 @@ public final class Channel {
|
||||
}
|
||||
}
|
||||
|
||||
private ChannelServer initServer(int port, int world, int channel) {
|
||||
ChannelServer channelServer = new ChannelServer(port, world, channel);
|
||||
private ChannelServer initServer(int port, int world, int channel, CharacterSaver characterSaver) {
|
||||
ChannelServer channelServer = new ChannelServer(port, world, channel, characterSaver);
|
||||
channelServer.start();
|
||||
return channelServer;
|
||||
}
|
||||
|
||||
@@ -33,6 +33,7 @@ import config.YamlConfig;
|
||||
import constants.id.ItemId;
|
||||
import constants.inventory.ItemConstants;
|
||||
import net.AbstractPacketHandler;
|
||||
import net.netty.GameViolationException;
|
||||
import net.packet.InPacket;
|
||||
import net.server.Server;
|
||||
import org.slf4j.Logger;
|
||||
@@ -287,8 +288,7 @@ public final class CashOperationHandler extends AbstractPacketHandler {
|
||||
|
||||
byte invType = p.readByte();
|
||||
if (invType < 1 || invType > 5) {
|
||||
c.disconnect(false, false);
|
||||
return;
|
||||
throw GameViolationException.inventoryType(invType);
|
||||
}
|
||||
|
||||
Inventory mi = chr.getInventory(InventoryType.getByType(invType));
|
||||
|
||||
@@ -24,6 +24,7 @@ package net.server.channel.handlers;
|
||||
import client.Client;
|
||||
import client.autoban.AutobanFactory;
|
||||
import net.AbstractPacketHandler;
|
||||
import net.netty.GameViolationException;
|
||||
import net.packet.InPacket;
|
||||
import net.server.Server;
|
||||
import service.ChannelService;
|
||||
@@ -45,8 +46,7 @@ public final class ChangeChannelHandler extends AbstractPacketHandler {
|
||||
c.getPlayer().getAutobanManager().setTimestamp(6, Server.getInstance().getCurrentTimestamp(), 3);
|
||||
if (c.getChannel() == channel) {
|
||||
AutobanFactory.GENERAL.alert(c.getPlayer(), "CCing to same channel.");
|
||||
c.disconnect(false, false);
|
||||
return;
|
||||
throw new GameViolationException("Change to same channel");
|
||||
} else if (c.getPlayer().getCashShop().isOpened() || c.getPlayer().getMiniGame() != null || c.getPlayer().getPlayerShop() != null) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -28,6 +28,7 @@ import client.inventory.manipulator.InventoryManipulator;
|
||||
import constants.id.ItemId;
|
||||
import constants.id.MapId;
|
||||
import net.AbstractPacketHandler;
|
||||
import net.netty.GameViolationException;
|
||||
import net.packet.InPacket;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
@@ -66,8 +67,7 @@ public final class ChangeMapHandler extends AbstractPacketHandler {
|
||||
}
|
||||
|
||||
if (chr.getCashShop().isOpened()) {
|
||||
c.disconnect(false, false);
|
||||
return;
|
||||
throw new GameViolationException("Changing channel inside cash shop");
|
||||
}
|
||||
|
||||
try {
|
||||
@@ -178,8 +178,7 @@ public final class ChangeMapHandler extends AbstractPacketHandler {
|
||||
final Character chr = c.getPlayer();
|
||||
|
||||
if (!chr.getCashShop().isOpened()) {
|
||||
c.disconnect(false, false);
|
||||
return;
|
||||
throw new GameViolationException("Enter map from cash shop, but is not in cash shop");
|
||||
}
|
||||
String[] socket = c.getChannelServer().getIP().split(":");
|
||||
chr.getCashShop().open(false);
|
||||
@@ -191,4 +190,4 @@ public final class ChangeMapHandler extends AbstractPacketHandler {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,6 +28,7 @@ import constants.game.GameConstants;
|
||||
import constants.id.MapId;
|
||||
import constants.skills.*;
|
||||
import database.drop.DropProvider;
|
||||
import net.netty.GameViolationException;
|
||||
import net.packet.InPacket;
|
||||
import server.StatEffect;
|
||||
import tools.PacketCreator;
|
||||
@@ -56,12 +57,8 @@ public final class CloseRangeDamageHandler extends AbstractDealDamageHandler {
|
||||
chr.getAutobanManager().spam(8);*/
|
||||
|
||||
AttackInfo attack = parseDamage(p, chr, false, false);
|
||||
if (chr.getBuffEffect(BuffStat.MORPH) != null) {
|
||||
if (chr.getBuffEffect(BuffStat.MORPH).isMorphWithoutAttack()) {
|
||||
// How are they attacking when the client won't let them?
|
||||
chr.getClient().disconnect(false, false);
|
||||
return;
|
||||
}
|
||||
if (chr.getBuffEffect(BuffStat.MORPH) != null && chr.getBuffEffect(BuffStat.MORPH).isMorphWithoutAttack()) {
|
||||
throw new GameViolationException("Attempt to attack with morph skill that disallows attacking");
|
||||
}
|
||||
|
||||
if (chr.getDojoEnergy() < 10000 && (attack.skill == 1009 || attack.skill == 10001009 || attack.skill == 20001009)) // PE hacking or maybe just lagging
|
||||
|
||||
@@ -26,6 +26,7 @@ import client.Client;
|
||||
import client.autoban.AutobanFactory;
|
||||
import client.command.CommandsExecutor;
|
||||
import net.AbstractPacketHandler;
|
||||
import net.netty.GameViolationException;
|
||||
import net.packet.InPacket;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
@@ -51,8 +52,7 @@ public final class GeneralChatHandler extends AbstractPacketHandler {
|
||||
if (s.length() > Byte.MAX_VALUE && !chr.isGM()) {
|
||||
AutobanFactory.PACKET_EDIT.alert(c.getPlayer(), c.getPlayer().getName() + " tried to packet edit in General Chat.");
|
||||
log.warn("Chr {} tried to send text with length of {}", c.getPlayer().getName(), s.length());
|
||||
c.disconnect(true, false);
|
||||
return;
|
||||
throw GameViolationException.textLength(s);
|
||||
}
|
||||
char heading = s.charAt(0);
|
||||
if (CommandsExecutor.isCommand(c, s)) {
|
||||
|
||||
@@ -26,6 +26,7 @@ import client.Character.FameStatus;
|
||||
import client.Client;
|
||||
import client.autoban.AutobanFactory;
|
||||
import net.AbstractPacketHandler;
|
||||
import net.netty.GameViolationException;
|
||||
import net.packet.InPacket;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
@@ -45,8 +46,7 @@ public final class GiveFameHandler extends AbstractPacketHandler {
|
||||
} else if (famechange != 1 && famechange != -1) {
|
||||
AutobanFactory.PACKET_EDIT.alert(c.getPlayer(), c.getPlayer().getName() + " tried to packet edit fame.");
|
||||
log.warn("Chr {} tried to fame hack with famechange {}", c.getPlayer().getName(), famechange);
|
||||
c.disconnect(true, false);
|
||||
return;
|
||||
throw new GameViolationException("Give too much fame");
|
||||
}
|
||||
|
||||
FameStatus status = player.canGiveFame(target);
|
||||
@@ -62,4 +62,4 @@ public final class GiveFameHandler extends AbstractPacketHandler {
|
||||
c.sendPacket(PacketCreator.giveFameErrorResponse(status == FameStatus.NOT_TODAY ? 3 : 4));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,6 +29,7 @@ import client.inventory.Item;
|
||||
import client.inventory.manipulator.InventoryManipulator;
|
||||
import config.YamlConfig;
|
||||
import net.AbstractPacketHandler;
|
||||
import net.netty.GameViolationException;
|
||||
import net.packet.InPacket;
|
||||
import net.server.Server;
|
||||
import server.ItemInformationProvider;
|
||||
@@ -49,8 +50,7 @@ public final class InventoryMergeHandler extends AbstractPacketHandler {
|
||||
|
||||
byte invType = p.readByte();
|
||||
if (invType < 1 || invType > 5) {
|
||||
c.disconnect(false, false);
|
||||
return;
|
||||
throw GameViolationException.inventoryType(invType);
|
||||
}
|
||||
|
||||
InventoryType inventoryType = InventoryType.getByType(invType);
|
||||
@@ -117,4 +117,4 @@ public final class InventoryMergeHandler extends AbstractPacketHandler {
|
||||
c.sendPacket(PacketCreator.finishedSort(inventoryType.getType()));
|
||||
c.sendPacket(PacketCreator.enableActions());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,6 +26,7 @@ import client.Client;
|
||||
import client.inventory.*;
|
||||
import config.YamlConfig;
|
||||
import net.AbstractPacketHandler;
|
||||
import net.netty.GameViolationException;
|
||||
import net.packet.InPacket;
|
||||
import net.server.Server;
|
||||
import server.ItemInformationProvider;
|
||||
@@ -298,8 +299,7 @@ public final class InventorySortHandler extends AbstractPacketHandler {
|
||||
|
||||
byte invType = p.readByte();
|
||||
if (invType < 1 || invType > 5) {
|
||||
c.disconnect(false, false);
|
||||
return;
|
||||
throw GameViolationException.inventoryType(invType);
|
||||
}
|
||||
|
||||
ArrayList<Item> itemarray = new ArrayList<>();
|
||||
|
||||
@@ -28,6 +28,7 @@ import client.inventory.InventoryType;
|
||||
import client.keybind.KeyBinding;
|
||||
import constants.game.GameConstants;
|
||||
import net.AbstractPacketHandler;
|
||||
import net.netty.GameViolationException;
|
||||
import net.packet.InPacket;
|
||||
|
||||
public final class KeymapChangeHandler extends AbstractPacketHandler {
|
||||
@@ -66,15 +67,13 @@ public final class KeymapChangeHandler extends AbstractPacketHandler {
|
||||
} else if (mode == 1) { // Auto HP Potion
|
||||
int itemID = p.readInt();
|
||||
if (itemID != 0 && c.getPlayer().getInventory(InventoryType.USE).findById(itemID) == null) {
|
||||
c.disconnect(false, false); // Don't let them send a packet with a use item they dont have.
|
||||
return;
|
||||
throw new GameViolationException("Set auto hp potion without owning the item");
|
||||
}
|
||||
c.getPlayer().changeKeybinding(91, new KeyBinding(7, itemID));
|
||||
} else if (mode == 2) { // Auto MP Potion
|
||||
int itemID = p.readInt();
|
||||
if (itemID != 0 && c.getPlayer().getInventory(InventoryType.USE).findById(itemID) == null) {
|
||||
c.disconnect(false, false); // Don't let them send a packet with a use item they dont have.
|
||||
return;
|
||||
throw new GameViolationException("Set auto mp potion without owning the item");
|
||||
}
|
||||
c.getPlayer().changeKeybinding(92, new KeyBinding(7, itemID));
|
||||
}
|
||||
|
||||
@@ -30,6 +30,7 @@ import constants.skills.Evan;
|
||||
import constants.skills.FPArchMage;
|
||||
import constants.skills.ILArchMage;
|
||||
import database.drop.DropProvider;
|
||||
import net.netty.GameViolationException;
|
||||
import net.packet.InPacket;
|
||||
import net.packet.Packet;
|
||||
import server.StatEffect;
|
||||
@@ -56,9 +57,7 @@ public final class MagicDamageHandler extends AbstractDealDamageHandler {
|
||||
|
||||
if (chr.getBuffEffect(BuffStat.MORPH) != null) {
|
||||
if (chr.getBuffEffect(BuffStat.MORPH).isMorphWithoutAttack()) {
|
||||
// How are they attacking when the client won't let them?
|
||||
chr.getClient().disconnect(false, false);
|
||||
return;
|
||||
throw new GameViolationException("Attempt to attack with morph skill that disallows attacking");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -25,6 +25,7 @@ import client.Character;
|
||||
import client.Client;
|
||||
import client.autoban.AutobanFactory;
|
||||
import net.AbstractPacketHandler;
|
||||
import net.netty.GameViolationException;
|
||||
import net.packet.InPacket;
|
||||
import net.server.Server;
|
||||
import net.server.world.World;
|
||||
@@ -53,9 +54,9 @@ public final class MultiChatHandler extends AbstractPacketHandler {
|
||||
if (chattext.length() > Byte.MAX_VALUE && !player.isGM()) {
|
||||
AutobanFactory.PACKET_EDIT.alert(c.getPlayer(), c.getPlayer().getName() + " tried to packet edit chats.");
|
||||
log.warn("Chr {} tried to send text with length of {}", c.getPlayer().getName(), chattext.length());
|
||||
c.disconnect(true, false);
|
||||
return;
|
||||
throw GameViolationException.textLength(chattext);
|
||||
}
|
||||
|
||||
World world = c.getWorldServer();
|
||||
if (type == 0) {
|
||||
world.buddyChat(recipients, player.getId(), player.getName(), chattext);
|
||||
|
||||
@@ -25,6 +25,7 @@ import client.Client;
|
||||
import client.autoban.AutobanFactory;
|
||||
import constants.inventory.ItemConstants;
|
||||
import net.AbstractPacketHandler;
|
||||
import net.netty.GameViolationException;
|
||||
import net.packet.InPacket;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
@@ -47,8 +48,7 @@ public final class NPCShopHandler extends AbstractPacketHandler {
|
||||
AutobanFactory.PACKET_EDIT.alert(c.getPlayer(),
|
||||
c.getPlayer().getName() + " tried to packet edit a npc shop.");
|
||||
log.warn("Chr {} tried to buy quantity {} of itemid {}", c.getPlayer().getName(), quantity, itemId);
|
||||
c.disconnect(true, false);
|
||||
return;
|
||||
throw new GameViolationException("Buy invalid amount of items");
|
||||
}
|
||||
c.getPlayer().getShop().buy(c, slot, itemId, quantity);
|
||||
break;
|
||||
|
||||
@@ -24,6 +24,7 @@ package net.server.channel.handlers;
|
||||
import client.Client;
|
||||
import client.autoban.AutobanFactory;
|
||||
import net.AbstractPacketHandler;
|
||||
import net.netty.GameViolationException;
|
||||
import net.packet.InPacket;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
@@ -47,9 +48,9 @@ public final class PetChatHandler extends AbstractPacketHandler {
|
||||
if (text.length() > Byte.MAX_VALUE) {
|
||||
AutobanFactory.PACKET_EDIT.alert(c.getPlayer(), c.getPlayer().getName() + " tried to packet edit with pets.");
|
||||
log.warn("Chr {} tried to send text with length of {}", c.getPlayer().getName(), text.length());
|
||||
c.disconnect(true, false);
|
||||
return;
|
||||
throw GameViolationException.textLength(text);
|
||||
}
|
||||
|
||||
c.getPlayer().getMap().broadcastMessage(c.getPlayer(), PacketCreator.petChat(c.getPlayer().getId(), pet, act, text), true);
|
||||
ChatLogger.log(c, "Pet", text);
|
||||
}
|
||||
|
||||
@@ -35,6 +35,7 @@ import constants.id.ItemId;
|
||||
import constants.inventory.ItemConstants;
|
||||
import database.character.CharacterSaver;
|
||||
import net.AbstractPacketHandler;
|
||||
import net.netty.GameViolationException;
|
||||
import net.packet.InPacket;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
@@ -674,8 +675,7 @@ public final class PlayerInteractionHandler extends AbstractPacketHandler {
|
||||
if (slot >= shop.getItems().size() || slot < 0) {
|
||||
AutobanFactory.PACKET_EDIT.alert(chr, chr.getName() + " tried to packet edit with a player shop.");
|
||||
log.warn("Chr {} tried to remove item at slot {}", chr.getName(), slot);
|
||||
c.disconnect(true, false);
|
||||
return;
|
||||
throw new GameViolationException("Remove item from invalid slot in shop");
|
||||
}
|
||||
|
||||
shop.takeItemBack(slot, chr);
|
||||
@@ -740,9 +740,9 @@ public final class PlayerInteractionHandler extends AbstractPacketHandler {
|
||||
if (quantity < 1) {
|
||||
AutobanFactory.PACKET_EDIT.alert(chr, chr.getName() + " tried to packet edit with a hired merchant and or player shop.");
|
||||
log.warn("Chr {} tried to buy item {} with quantity {}", chr.getName(), itemid, quantity);
|
||||
c.disconnect(true, false);
|
||||
return;
|
||||
throw new GameViolationException("Buy item with invalid quantity");
|
||||
}
|
||||
|
||||
PlayerShop shop = chr.getPlayerShop();
|
||||
HiredMerchant merchant = chr.getHiredMerchant();
|
||||
if (shop != null && shop.isVisitor(chr)) {
|
||||
@@ -769,8 +769,7 @@ public final class PlayerInteractionHandler extends AbstractPacketHandler {
|
||||
if (slot >= merchant.getItems().size() || slot < 0) {
|
||||
AutobanFactory.PACKET_EDIT.alert(chr, chr.getName() + " tried to packet edit with a hired merchant.");
|
||||
log.warn("Chr {} tried to remove item at slot {}", chr.getName(), slot);
|
||||
c.disconnect(true, false);
|
||||
return;
|
||||
throw new GameViolationException("Withdraw item from merchant with invalid slot");
|
||||
}
|
||||
|
||||
merchant.takeItemBack(slot, chr, chrSaver);
|
||||
|
||||
@@ -29,6 +29,7 @@ import config.YamlConfig;
|
||||
import constants.game.GameConstants;
|
||||
import database.character.CharacterLoader;
|
||||
import net.AbstractPacketHandler;
|
||||
import net.netty.GameViolationException;
|
||||
import net.packet.InPacket;
|
||||
import net.server.PlayerBuffValueHolder;
|
||||
import net.server.Server;
|
||||
@@ -108,8 +109,7 @@ public final class PlayerLoggedinHandler extends AbstractPacketHandler {
|
||||
try {
|
||||
World wserv = server.getWorld(c.getWorld());
|
||||
if (wserv == null) {
|
||||
c.disconnect(true, false);
|
||||
return;
|
||||
throw new GameViolationException("World not found");
|
||||
}
|
||||
|
||||
Channel cserv = wserv.getChannel(c.getChannel());
|
||||
@@ -118,8 +118,7 @@ public final class PlayerLoggedinHandler extends AbstractPacketHandler {
|
||||
cserv = wserv.getChannel(c.getChannel());
|
||||
|
||||
if (cserv == null) {
|
||||
c.disconnect(true, false);
|
||||
return;
|
||||
throw new GameViolationException("Channel not found");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -129,8 +128,7 @@ public final class PlayerLoggedinHandler extends AbstractPacketHandler {
|
||||
if (player == null) {
|
||||
hwid = SessionCoordinator.getInstance().pickLoginSessionHwid(c);
|
||||
if (hwid == null) {
|
||||
c.disconnect(true, false);
|
||||
return;
|
||||
throw new GameViolationException("Unable to pick hwid");
|
||||
}
|
||||
} else {
|
||||
hwid = player.getClient().getHwid();
|
||||
@@ -139,8 +137,7 @@ public final class PlayerLoggedinHandler extends AbstractPacketHandler {
|
||||
c.setHwid(hwid);
|
||||
|
||||
if (!server.validateCharacteridInTransition(c, chrId)) {
|
||||
c.disconnect(true, false);
|
||||
return;
|
||||
throw new GameViolationException("Attempt to enter game without chr id in transition");
|
||||
}
|
||||
|
||||
boolean newcomer = false;
|
||||
@@ -150,8 +147,7 @@ public final class PlayerLoggedinHandler extends AbstractPacketHandler {
|
||||
player = loadedChr.get();
|
||||
newcomer = true;
|
||||
} else {
|
||||
c.disconnect(true, false);
|
||||
return;
|
||||
throw new GameViolationException("Unable to load chr");
|
||||
}
|
||||
}
|
||||
c.setPlayer(player);
|
||||
@@ -184,7 +180,7 @@ public final class PlayerLoggedinHandler extends AbstractPacketHandler {
|
||||
c.setAccID(0);
|
||||
|
||||
if (state == Client.LOGIN_LOGGEDIN) {
|
||||
c.disconnect(true, false);
|
||||
throw new GameViolationException("Attempt to log in when already logged in");
|
||||
} else {
|
||||
c.sendPacket(PacketCreator.getAfterLoginError(7));
|
||||
}
|
||||
|
||||
@@ -34,6 +34,7 @@ import constants.id.MapId;
|
||||
import constants.inventory.ItemConstants;
|
||||
import constants.skills.*;
|
||||
import database.drop.DropProvider;
|
||||
import net.netty.GameViolationException;
|
||||
import net.packet.InPacket;
|
||||
import net.packet.Packet;
|
||||
import org.slf4j.Logger;
|
||||
@@ -67,9 +68,7 @@ public final class RangedAttackHandler extends AbstractDealDamageHandler {
|
||||
|
||||
if (chr.getBuffEffect(BuffStat.MORPH) != null) {
|
||||
if (chr.getBuffEffect(BuffStat.MORPH).isMorphWithoutAttack()) {
|
||||
// How are they attacking when the client won't let them?
|
||||
chr.getClient().disconnect(false, false);
|
||||
return;
|
||||
throw new GameViolationException("Attempt to attack with morph skill that disallows attacking");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -27,6 +27,7 @@ import constants.id.ItemId;
|
||||
import constants.id.NpcId;
|
||||
import constants.inventory.ItemConstants;
|
||||
import net.AbstractPacketHandler;
|
||||
import net.netty.GameViolationException;
|
||||
import net.packet.InPacket;
|
||||
import scripting.npc.NPCScriptManager;
|
||||
|
||||
@@ -40,16 +41,13 @@ public final class RemoteGachaponHandler extends AbstractPacketHandler {
|
||||
int gacha = p.readInt();
|
||||
if (ticket != ItemId.REMOTE_GACHAPON_TICKET) {
|
||||
AutobanFactory.GENERAL.alert(c.getPlayer(), " Tried to use RemoteGachaponHandler with item id: " + ticket);
|
||||
c.disconnect(false, false);
|
||||
return;
|
||||
throw new GameViolationException("Use Remote gachapon without owning the item");
|
||||
} else if (gacha < 0 || gacha > 11) {
|
||||
AutobanFactory.GENERAL.alert(c.getPlayer(), " Tried to use RemoteGachaponHandler with mode: " + gacha);
|
||||
c.disconnect(false, false);
|
||||
return;
|
||||
throw new GameViolationException("Use Remote gachapon with invalid mode");
|
||||
} else if (c.getPlayer().getInventory(ItemConstants.getInventoryType(ticket)).countById(ticket) < 1) {
|
||||
AutobanFactory.GENERAL.alert(c.getPlayer(), " Tried to use RemoteGachaponHandler without a ticket.");
|
||||
c.disconnect(false, false);
|
||||
return;
|
||||
throw new GameViolationException("Use Remote gachapon without a ticket");
|
||||
}
|
||||
int npcId = NpcId.GACHAPON_HENESYS;
|
||||
if (gacha != 8 && gacha != 9) {
|
||||
|
||||
@@ -26,6 +26,7 @@ import client.Client;
|
||||
import client.SkillMacro;
|
||||
import client.autoban.AutobanFactory;
|
||||
import net.AbstractPacketHandler;
|
||||
import net.netty.GameViolationException;
|
||||
import net.packet.InPacket;
|
||||
|
||||
public final class SkillMacroHandler extends AbstractPacketHandler {
|
||||
@@ -42,8 +43,7 @@ public final class SkillMacroHandler extends AbstractPacketHandler {
|
||||
String name = p.readString();
|
||||
if (name.length() > 12) {
|
||||
AutobanFactory.PACKET_EDIT.alert(chr, "Invalid name length " + name + " (" + name.length() + ") for skill macro.");
|
||||
c.disconnect(false, false);
|
||||
break;
|
||||
throw GameViolationException.textLength(name);
|
||||
}
|
||||
|
||||
int shout = p.readByte();
|
||||
|
||||
@@ -25,6 +25,7 @@ import client.Character;
|
||||
import client.Client;
|
||||
import client.autoban.AutobanFactory;
|
||||
import net.AbstractPacketHandler;
|
||||
import net.netty.GameViolationException;
|
||||
import net.packet.InPacket;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
@@ -96,8 +97,7 @@ public final class WhisperHandler extends AbstractPacketHandler {
|
||||
if (message.length() > Byte.MAX_VALUE) {
|
||||
AutobanFactory.PACKET_EDIT.alert(user, user.getName() + " tried to packet edit with whispers.");
|
||||
log.warn("Chr {} tried to send text with length of {}", user.getName(), message.length());
|
||||
user.getClient().disconnect(true, false);
|
||||
return;
|
||||
throw GameViolationException.textLength(message);
|
||||
}
|
||||
|
||||
ChatLogger.log(user.getClient(), "Whisper To " + target.getName(), message);
|
||||
|
||||
@@ -2,6 +2,7 @@ package net.server.handlers.login;
|
||||
|
||||
import client.Client;
|
||||
import net.AbstractPacketHandler;
|
||||
import net.netty.GameViolationException;
|
||||
import net.packet.InPacket;
|
||||
import tools.PacketCreator;
|
||||
|
||||
@@ -16,11 +17,11 @@ public final class AcceptToSHandler extends AbstractPacketHandler {
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void handlePacket(InPacket p, Client c) {
|
||||
public void handlePacket(InPacket p, Client c) {
|
||||
if (p.available() == 0 || p.readByte() != 1 || c.acceptToS()) {
|
||||
c.disconnect(false, false);//Client dc's but just because I am cool I do this (:
|
||||
return;
|
||||
throw new GameViolationException("ToS not accepted");
|
||||
}
|
||||
|
||||
if (c.finishLogin() == 0) {
|
||||
c.sendPacket(PacketCreator.getAuthSuccess(c));
|
||||
} else {
|
||||
|
||||
@@ -27,6 +27,7 @@ import client.creator.novice.LegendCreator;
|
||||
import client.creator.novice.NoblesseCreator;
|
||||
import constants.id.ItemId;
|
||||
import net.AbstractPacketHandler;
|
||||
import net.netty.GameViolationException;
|
||||
import net.packet.InPacket;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
@@ -80,8 +81,7 @@ public final class CreateCharHandler extends AbstractPacketHandler {
|
||||
for (int item : items) {
|
||||
if (!isLegal(item)) {
|
||||
log.warn("Owner from account {} tried to packet edit in chr creation", c.getAccountName());
|
||||
c.disconnect(true, false);
|
||||
return;
|
||||
throw new GameViolationException("Create character with invalid equip");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -105,4 +105,4 @@ public final class CreateCharHandler extends AbstractPacketHandler {
|
||||
c.sendPacket(PacketCreator.deleteCharResponse(0, 9));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user