package io.statik.report; import io.netty.buffer.ByteBuf; import io.netty.buffer.ByteBufAllocator; import io.netty.buffer.ByteBufUtil; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelInboundHandlerAdapter; import io.netty.util.ReferenceCountUtil; import java.net.InetSocketAddress; import java.net.SocketAddress; import java.nio.CharBuffer; import java.nio.charset.Charset; import java.util.logging.Level; /** * Class to handle receiving messages. */ public class ReportHandler extends ChannelInboundHandlerAdapter { private final ReportServer rs; private final MessageHandler mh; /** * Creates a new ReportHandler and initializes its {@link io.statik.report.MessageHandler}. * * @param rs ReportServer this is running from */ public ReportHandler(final ReportServer rs) { this.rs = rs; this.mh = new MessageHandler(rs); } private ByteBuf encodeString(final ByteBufAllocator bba, final String string) { return ByteBufUtil.encodeString(bba, CharBuffer.wrap(string), Charset.forName("UTF-8")); } @Override public void channelRead(final ChannelHandlerContext ctx, final Object msg) throws Exception { final SocketAddress sa = ctx.channel().remoteAddress(); if (!(sa instanceof InetSocketAddress)) return; final InetSocketAddress isa = (InetSocketAddress) sa; Client c; synchronized (this.rs.getClients()) { c = this.rs.getClient(isa); } if (c == null) c = new Client(this.rs, isa); if (c.getStage() == Stage.NO_DATA) { ctx.writeAndFlush(this.encodeString(ctx.alloc(), "No data should be sent.")); return; } try { final Object write = this.mh.handleMessage(msg, c); final ByteBuf bb; if (write instanceof String) { bb = this.encodeString(ctx.alloc(), (String) write); } else if (write instanceof ByteBuf) { bb = (ByteBuf) write; } else return; ctx.writeAndFlush(bb); } catch (final Throwable t) { this.rs.getLogger().warning("An exception occurred while reading a request:"); this.rs.getLogger().log(Level.WARNING, t.getMessage(), t); t.printStackTrace(); } finally { ReferenceCountUtil.release(msg); } } public static enum Stage { INTRODUCTION, DATA, NO_DATA } }