package divconq.test.net; import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.atomic.AtomicLong; import divconq.lang.chars.Utf8Decoder; import divconq.net.ssl.SslHandshakeCompletionEvent; import io.netty.buffer.ByteBuf; import io.netty.channel.Channel; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelInboundHandlerAdapter; public class LocalEchoServerHandler extends ChannelInboundHandlerAdapter { protected Thread worker = null; protected LinkedBlockingQueue<String> queue = new LinkedBlockingQueue<String>(); protected Channel chan = null; protected AtomicLong gotten = new AtomicLong(); protected AtomicLong proc = new AtomicLong(); public LocalEchoServerHandler() { this.worker = new Thread(new Runnable() { @Override public void run() { while (true) { try { String msg = queue.take(); long gg = gotten.get(); long pp = proc.incrementAndGet(); if (msg.length() == 512) System.out.println("Processing " + pp + " of " + gg); else System.out.println("ERROR Processing " + pp + " of " + gg + " ERROR =============================================================="); // do processing //Thread.sleep(2); //System.out.println("Echo and read: " + msg); //ByteBuf b = Unpooled.wrappedBuffer(Utf8Encoder.encode(">" + msg + "<")); //chan.writeAndFlush(b); //chan.config().setAutoRead(true); if (queue.size() == 0) chan.read(); } catch (InterruptedException x) { } } } }); this.worker.setDaemon(true); this.worker.start(); } private ByteBuf buf = null; @Override public void handlerAdded(ChannelHandlerContext ctx) { this.buf = ctx.alloc().buffer(512); // (1) } @Override public void handlerRemoved(ChannelHandlerContext ctx) { this.buf.release(); // (1) this.buf = null; } @Override public void channelActive(ChannelHandlerContext ctx) throws Exception { super.channelActive(ctx); // allow first read ctx.channel().read(); } @Override public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { if (this.chan == null) this.chan = ctx.channel(); this.chan.config().setAutoRead(false); ByteBuf m = (ByteBuf) msg; boolean more = m.readableBytes() > 0; //System.out.println("got: " + m.readableBytes()); while (more) { int amt = Math.min(this.buf.writableBytes(), m.readableBytes()); this.buf.writeBytes(m, m.readerIndex(), amt); // (2) m.skipBytes(amt); if (m.readableBytes() == 0) { m.release(); more = false; } if (this.buf.writerIndex() == 512) { this.queue.add(Utf8Decoder.decode(this.buf).toString()); this.gotten.incrementAndGet(); this.buf.clear(); } } // Write back as received //ctx.write(msg); } @Override public void channelReadComplete(ChannelHandlerContext ctx) throws Exception { //ctx.flush(); //System.out.println("read complete"); } @Override public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) { cause.printStackTrace(); ctx.close(); } @Override public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception { // on success the request first read if (evt == SslHandshakeCompletionEvent.SUCCESS) { ctx.read(); } } }