diff --git a/src/main/java/com/github/steveice10/packetlib/event/session/PacketErrorEvent.java b/src/main/java/com/github/steveice10/packetlib/event/session/PacketErrorEvent.java new file mode 100644 index 00000000..735ca58b --- /dev/null +++ b/src/main/java/com/github/steveice10/packetlib/event/session/PacketErrorEvent.java @@ -0,0 +1,68 @@ +package com.github.steveice10.packetlib.event.session; + +import com.github.steveice10.packetlib.Session; + +/** + * Called when a session encounters an error while reading or writing packet data. + */ +public class PacketErrorEvent implements SessionEvent { + private Session session; + private Throwable cause; + private boolean suppress = false; + + /** + * Creates a new SessionErrorEvent instance. + * + * @param session Session that the error came from. + * @param cause Cause of the error. + */ + public PacketErrorEvent(Session session, Throwable cause) { + this.session = session; + this.cause = cause; + } + + /** + * Gets the session involved in this event. + * + * @return The event's session. + */ + public Session getSession() { + return this.session; + } + + /** + * Gets the Throwable responsible for the error. + * + * @return The Throwable responsible for the error. + */ + public Throwable getCause() { + return this.cause; + } + + /** + * Gets whether the error should be suppressed. If the error is not suppressed, + * it will be passed on through internal error handling and disconnect the session. + * + * The default value is false. + * + * @return Whether the error should be suppressed. + */ + public boolean shouldSuppress() { + return this.suppress; + } + + /** + * Sets whether the error should be suppressed. If the error is not suppressed, + * it will be passed on through internal error handling and disconnect the session. + * + * @param suppress Whether the error should be suppressed. + */ + public void setSuppress(boolean suppress) { + this.suppress = suppress; + } + + @Override + public void call(SessionListener listener) { + listener.packetError(this); + } +} diff --git a/src/main/java/com/github/steveice10/packetlib/event/session/SessionAdapter.java b/src/main/java/com/github/steveice10/packetlib/event/session/SessionAdapter.java index 3d20e8ae..7dd5b211 100644 --- a/src/main/java/com/github/steveice10/packetlib/event/session/SessionAdapter.java +++ b/src/main/java/com/github/steveice10/packetlib/event/session/SessionAdapter.java @@ -16,6 +16,10 @@ public class SessionAdapter implements SessionListener { public void packetSent(PacketSentEvent event) { } + @Override + public void packetError(PacketErrorEvent event) { + } + @Override public void connected(ConnectedEvent event) { } diff --git a/src/main/java/com/github/steveice10/packetlib/event/session/SessionListener.java b/src/main/java/com/github/steveice10/packetlib/event/session/SessionListener.java index 23951cc8..cf1f3a4c 100644 --- a/src/main/java/com/github/steveice10/packetlib/event/session/SessionListener.java +++ b/src/main/java/com/github/steveice10/packetlib/event/session/SessionListener.java @@ -25,6 +25,13 @@ public interface SessionListener { */ public void packetSent(PacketSentEvent event); + /** + * Called when a session encounters an error while reading or writing packet data. + * + * @param event Data relating to the event. + */ + public void packetError(PacketErrorEvent event); + /** * Called when a session connects. * diff --git a/src/main/java/com/github/steveice10/packetlib/tcp/TcpPacketCodec.java b/src/main/java/com/github/steveice10/packetlib/tcp/TcpPacketCodec.java index fcb4bc8a..08e3be9e 100644 --- a/src/main/java/com/github/steveice10/packetlib/tcp/TcpPacketCodec.java +++ b/src/main/java/com/github/steveice10/packetlib/tcp/TcpPacketCodec.java @@ -1,6 +1,7 @@ package com.github.steveice10.packetlib.tcp; import com.github.steveice10.packetlib.Session; +import com.github.steveice10.packetlib.event.session.PacketErrorEvent; import com.github.steveice10.packetlib.event.session.PacketReceivedEvent; import com.github.steveice10.packetlib.io.NetInput; import com.github.steveice10.packetlib.io.NetOutput; @@ -23,8 +24,16 @@ public class TcpPacketCodec extends ByteToMessageCodec { @Override public void encode(ChannelHandlerContext ctx, Packet packet, ByteBuf buf) throws Exception { NetOutput out = new ByteBufNetOutput(buf); - this.session.getPacketProtocol().getPacketHeader().writePacketId(out, this.session.getPacketProtocol().getOutgoingId(packet)); - packet.write(out); + try { + this.session.getPacketProtocol().getPacketHeader().writePacketId(out, this.session.getPacketProtocol().getOutgoingId(packet)); + packet.write(out); + } catch(Throwable t) { + PacketErrorEvent e = new PacketErrorEvent(this.session, t); + this.session.callEvent(e); + if(!e.shouldSuppress()) { + throw t; + } + } } @Override @@ -37,8 +46,19 @@ public class TcpPacketCodec extends ByteToMessageCodec { return; } - Packet packet = this.session.getPacketProtocol().createIncomingPacket(id); - packet.read(in); + Packet packet; + try { + packet = this.session.getPacketProtocol().createIncomingPacket(id); + packet.read(in); + } catch(Throwable t) { + PacketErrorEvent e = new PacketErrorEvent(this.session, t); + this.session.callEvent(e); + if(!e.shouldSuppress()) { + throw t; + } + + return; + } if(buf.readableBytes() > 0) { throw new IllegalStateException("Packet \"" + packet.getClass().getSimpleName() + "\" not fully read.");