Ensure that a user implements flush() or inboundBufferUpdated()

- Also prohibited a user from overriding
  ChannelInbound(Byte|Message)HandlerAdapter.  If a user wants to do
  that, he or she should extend ChannelInboundHandlerAdapter instead.
This commit is contained in:
Trustin Lee 2012-06-10 10:48:11 +09:00
parent b6d5593e6a
commit 87f52aa604
20 changed files with 99 additions and 116 deletions

View File

@ -22,18 +22,18 @@ import io.netty.channel.ChannelInboundByteHandlerAdapter;
public abstract class ByteToByteDecoder extends ChannelInboundByteHandlerAdapter {
@Override
public void inboundBufferUpdated(ChannelHandlerContext ctx) throws Exception {
callDecode(ctx);
public void inboundBufferUpdated(ChannelHandlerContext ctx, ChannelBuffer in) throws Exception {
callDecode(ctx, in, ctx.nextOutboundByteBuffer());
}
@Override
public void channelInactive(ChannelHandlerContext ctx) throws Exception {
ChannelBuffer in = ctx.inboundByteBuffer();
ChannelBuffer out = ctx.nextInboundByteBuffer();
if (!in.readable()) {
callDecode(ctx);
callDecode(ctx, in, out);
}
ChannelBuffer out = ctx.nextInboundByteBuffer();
int oldOutSize = out.readableBytes();
try {
decodeLast(ctx, in, out);
@ -53,10 +53,7 @@ public abstract class ByteToByteDecoder extends ChannelInboundByteHandlerAdapter
ctx.fireChannelInactive();
}
private void callDecode(ChannelHandlerContext ctx) {
ChannelBuffer in = ctx.inboundByteBuffer();
ChannelBuffer out = ctx.nextInboundByteBuffer();
private void callDecode(ChannelHandlerContext ctx, ChannelBuffer in, ChannelBuffer out) {
int oldOutSize = out.readableBytes();
while (in.readable()) {
int oldInSize = in.readableBytes();

View File

@ -16,12 +16,14 @@
package io.netty.handler.codec;
import io.netty.buffer.ChannelBuffer;
import io.netty.channel.ChannelBufferHolder;
import io.netty.channel.ChannelBufferHolders;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandler;
import io.netty.channel.ChannelInboundByteHandlerAdapter;
import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.channel.ChannelPipeline;
public abstract class ByteToMessageDecoder<O> extends ChannelInboundByteHandlerAdapter {
public abstract class ByteToMessageDecoder<O> extends ChannelInboundHandlerAdapter<Byte> {
private ChannelHandlerContext ctx;
@ -31,6 +33,11 @@ public abstract class ByteToMessageDecoder<O> extends ChannelInboundByteHandlerA
super.beforeAdd(ctx);
}
@Override
public ChannelBufferHolder<Byte> newInboundBuffer(ChannelHandlerContext ctx) throws Exception {
return ChannelBufferHolders.byteBuffer();
}
@Override
public void inboundBufferUpdated(ChannelHandlerContext ctx) throws Exception {
callDecode(ctx);

View File

@ -47,28 +47,28 @@ final class CodecUtil {
}
if (inbound) {
try {
if (ctx.hasNextInboundMessageBuffer()) {
ctx.nextInboundMessageBuffer().add(msg);
return true;
} catch (NoSuchBufferException e) {
if (msg instanceof ChannelBuffer) {
ChannelBuffer altDst = ctx.nextInboundByteBuffer();
ChannelBuffer src = (ChannelBuffer) msg;
altDst.writeBytes(src, src.readerIndex(), src.readableBytes());
return true;
}
}
if (msg instanceof ChannelBuffer && ctx.hasNextInboundByteBuffer()) {
ChannelBuffer altDst = ctx.nextInboundByteBuffer();
ChannelBuffer src = (ChannelBuffer) msg;
altDst.writeBytes(src, src.readerIndex(), src.readableBytes());
return true;
}
} else {
try {
if (ctx.hasNextOutboundMessageBuffer()) {
ctx.nextOutboundMessageBuffer().add(msg);
return true;
} catch (NoSuchBufferException e) {
if (msg instanceof ChannelBuffer) {
ChannelBuffer altDst = ctx.nextOutboundByteBuffer();
ChannelBuffer src = (ChannelBuffer) msg;
altDst.writeBytes(src, src.readerIndex(), src.readableBytes());
return true;
}
}
if (msg instanceof ChannelBuffer && ctx.hasNextOutboundByteBuffer()) {
ChannelBuffer altDst = ctx.nextOutboundByteBuffer();
ChannelBuffer src = (ChannelBuffer) msg;
altDst.writeBytes(src, src.readerIndex(), src.readableBytes());
return true;
}
}

View File

@ -15,12 +15,19 @@
*/
package io.netty.handler.codec;
import io.netty.channel.ChannelBufferHolder;
import io.netty.channel.ChannelBufferHolders;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundMessageHandlerAdapter;
import io.netty.channel.ChannelInboundHandlerAdapter;
import java.util.Queue;
public abstract class MessageToMessageDecoder<I, O> extends ChannelInboundMessageHandlerAdapter<I> {
public abstract class MessageToMessageDecoder<I, O> extends ChannelInboundHandlerAdapter<I> {
@Override
public ChannelBufferHolder<I> newInboundBuffer(ChannelHandlerContext ctx) throws Exception {
return ChannelBufferHolders.messageBuffer();
}
@Override
public void inboundBufferUpdated(ChannelHandlerContext ctx)

View File

@ -53,16 +53,14 @@ public class PortUnificationServerHandler extends ChannelInboundByteHandlerAdapt
}
@Override
public void inboundBufferUpdated(ChannelHandlerContext ctx) throws Exception {
ChannelBuffer buffer = ctx.inboundByteBuffer();
public void inboundBufferUpdated(ChannelHandlerContext ctx, ChannelBuffer in) throws Exception {
// Will use the first two bytes to detect a protocol.
if (buffer.readableBytes() < 2) {
if (in.readableBytes() < 2) {
return;
}
final int magic1 = buffer.getUnsignedByte(buffer.readerIndex());
final int magic2 = buffer.getUnsignedByte(buffer.readerIndex() + 1);
final int magic1 = in.getUnsignedByte(in.readerIndex());
final int magic2 = in.getUnsignedByte(in.readerIndex() + 1);
if (isSsl(magic1)) {
enableSsl(ctx);
@ -74,13 +72,13 @@ public class PortUnificationServerHandler extends ChannelInboundByteHandlerAdapt
switchToFactorial(ctx);
} else {
// Unknown protocol; discard everything and close the connection.
buffer.clear();
in.clear();
ctx.close();
return;
}
// Forward the current read buffer as is to the new handlers.
ctx.nextInboundByteBuffer().writeBytes(buffer);
ctx.nextInboundByteBuffer().writeBytes(in);
ctx.fireInboundBufferUpdated();
}

View File

@ -34,8 +34,7 @@ public class HexDumpProxyBackendHandler extends ChannelInboundByteHandlerAdapter
}
@Override
public void inboundBufferUpdated(ChannelHandlerContext ctx) throws Exception {
ChannelBuffer in = ctx.inboundByteBuffer();
public void inboundBufferUpdated(ChannelHandlerContext ctx, ChannelBuffer in) throws Exception {
ChannelBuffer out = inboundChannel.outboundByteBuffer();
out.discardReadBytes();
out.writeBytes(in);

View File

@ -66,8 +66,7 @@ public class HexDumpProxyFrontendHandler extends ChannelInboundByteHandlerAdapte
}
@Override
public void inboundBufferUpdated(ChannelHandlerContext ctx) throws Exception {
ChannelBuffer in = ctx.inboundByteBuffer();
public void inboundBufferUpdated(ChannelHandlerContext ctx, ChannelBuffer in) throws Exception {
ChannelBuffer out = outboundChannel.outboundByteBuffer();
out.discardReadBytes();
out.writeBytes(in);

View File

@ -218,4 +218,10 @@ public class BlockingReadHandler<E> extends ChannelInboundMessageHandlerAdapter<
queue.add(e);
}
}
@Override
public void messageReceived(ChannelHandlerContext ctx, Object msg) throws Exception {
// TODO Auto-generated method stub
}
}

View File

@ -144,11 +144,8 @@ public class ChunkedWriteHandlerTest {
@Override
public void flush(ChannelHandlerContext ctx, ChannelFuture future) throws Exception {
super.flush(ctx, future);
future.setSuccess();
}
};
EmbeddedMessageChannel ch = new EmbeddedMessageChannel(new ChunkedWriteHandler(), testHandler);

View File

@ -22,8 +22,8 @@ import io.netty.buffer.ChannelBuffer;
import io.netty.buffer.ChannelBuffers;
import io.netty.channel.Channel;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundMessageHandlerAdapter;
import io.netty.channel.ChannelInboundByteHandlerAdapter;
import io.netty.channel.ChannelInboundMessageHandlerAdapter;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.socket.SocketChannel;
import io.netty.handler.codec.spdy.SpdyConstants;
@ -255,10 +255,9 @@ public class SocketSpdyEchoTest extends AbstractSocketTest {
}
@Override
public void inboundBufferUpdated(ChannelHandlerContext ctx) throws Exception {
ChannelBuffer m = ctx.inboundByteBuffer();
byte[] actual = new byte[m.readableBytes()];
m.readBytes(actual);
public void inboundBufferUpdated(ChannelHandlerContext ctx, ChannelBuffer in) throws Exception {
byte[] actual = new byte[in.readableBytes()];
in.readBytes(actual);
int lastIdx = counter;
for (int i = 0; i < actual.length; i ++) {

View File

@ -16,12 +16,14 @@
package io.netty.bootstrap;
import io.netty.channel.Channel;
import io.netty.channel.ChannelBufferHolder;
import io.netty.channel.ChannelBufferHolders;
import io.netty.channel.ChannelException;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelFutureListener;
import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundMessageHandlerAdapter;
import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.ChannelPipeline;
@ -228,7 +230,11 @@ public class ServerBootstrap {
validate();
}
private class Acceptor extends ChannelInboundMessageHandlerAdapter<Channel> {
private class Acceptor extends ChannelInboundHandlerAdapter<Channel> {
@Override
public ChannelBufferHolder<Channel> newInboundBuffer(ChannelHandlerContext ctx) throws Exception {
return ChannelBufferHolders.messageBuffer();
}
@Override
public void inboundBufferUpdated(ChannelHandlerContext ctx) {

View File

@ -15,10 +15,7 @@
*/
package io.netty.channel;
import io.netty.buffer.ChannelBuffer;
import java.net.SocketAddress;
import java.util.Queue;
public class ChannelHandlerAdapter extends ChannelStateHandlerAdapter implements ChannelOperationHandler {
@ -51,27 +48,11 @@ public class ChannelHandlerAdapter extends ChannelStateHandlerAdapter implements
@Override
public void flush(ChannelHandlerContext ctx, ChannelFuture future) throws Exception {
flush0(ctx, future);
}
static <O> void flush0(ChannelHandlerContext ctx, ChannelFuture future) {
if (ctx.hasOutboundMessageBuffer()) {
Queue<O> out = ctx.outboundMessageBuffer();
Queue<Object> nextOut = ctx.nextOutboundMessageBuffer();
for (;;) {
O msg = out.poll();
if (msg == null) {
break;
}
nextOut.add(msg);
}
} else if (ctx.hasOutboundByteBuffer()) {
ChannelBuffer out = ctx.outboundByteBuffer();
ChannelBuffer nextOut = ctx.nextOutboundByteBuffer();
nextOut.writeBytes(out);
out.discardReadBytes();
if (this instanceof ChannelOutboundHandler) {
throw new IllegalStateException(
"flush(...) must be overridden by " + getClass().getName() +
", which implements " + ChannelOutboundHandler.class.getSimpleName());
}
ctx.flush(future);
}
}

View File

@ -18,7 +18,7 @@ package io.netty.channel;
import io.netty.buffer.ChannelBuffer;
public class ChannelInboundByteHandlerAdapter extends ChannelInboundHandlerAdapter<Byte> {
public abstract class ChannelInboundByteHandlerAdapter extends ChannelInboundHandlerAdapter<Byte> {
@Override
public ChannelBufferHolder<Byte> newInboundBuffer(ChannelHandlerContext ctx) throws Exception {
@ -26,12 +26,16 @@ public class ChannelInboundByteHandlerAdapter extends ChannelInboundHandlerAdapt
}
@Override
public void inboundBufferUpdated(ChannelHandlerContext ctx) throws Exception {
inboundBufferUpdated(ctx, ctx.inboundByteBuffer());
public final void inboundBufferUpdated(ChannelHandlerContext ctx) throws Exception {
ChannelBuffer in = ctx.inboundByteBuffer();
try {
inboundBufferUpdated(ctx, in);
} finally {
if (!in.readable()) {
in.discardReadBytes();
}
}
}
public void inboundBufferUpdated(ChannelHandlerContext ctx, ChannelBuffer in) throws Exception {
ctx.nextInboundByteBuffer().writeBytes(in);
in.discardReadBytes();
}
public abstract void inboundBufferUpdated(ChannelHandlerContext ctx, ChannelBuffer in) throws Exception;
}

View File

@ -18,5 +18,6 @@ package io.netty.channel;
public abstract class ChannelInboundHandlerAdapter<I> extends ChannelStateHandlerAdapter
implements ChannelInboundHandler<I> {
// Useful when you have to create an anonymous class
@Override
public abstract void inboundBufferUpdated(ChannelHandlerContext ctx) throws Exception;
}

View File

@ -17,7 +17,7 @@ package io.netty.channel;
import java.util.Queue;
public class ChannelInboundMessageHandlerAdapter<I> extends ChannelInboundHandlerAdapter<I> {
public abstract class ChannelInboundMessageHandlerAdapter<I> extends ChannelInboundHandlerAdapter<I> {
@Override
public ChannelBufferHolder<I> newInboundBuffer(ChannelHandlerContext ctx) throws Exception {
@ -25,7 +25,7 @@ public class ChannelInboundMessageHandlerAdapter<I> extends ChannelInboundHandle
}
@Override
public void inboundBufferUpdated(ChannelHandlerContext ctx) throws Exception {
public final void inboundBufferUpdated(ChannelHandlerContext ctx) throws Exception {
Queue<I> in = ctx.inboundMessageBuffer();
for (;;) {
I msg = in.poll();
@ -34,14 +34,11 @@ public class ChannelInboundMessageHandlerAdapter<I> extends ChannelInboundHandle
}
try {
messageReceived(ctx, msg);
ctx.fireInboundBufferUpdated();
} catch (Throwable t) {
ctx.fireExceptionCaught(t);
}
}
}
public void messageReceived(ChannelHandlerContext ctx, I msg) throws Exception {
ctx.nextInboundMessageBuffer().add(msg);
}
public abstract void messageReceived(ChannelHandlerContext ctx, I msg) throws Exception;
}

View File

@ -84,6 +84,11 @@ public class ChannelOperationHandlerAdapter implements ChannelOperationHandler {
@Override
public void flush(ChannelHandlerContext ctx, ChannelFuture future)
throws Exception {
ChannelHandlerAdapter.flush0(ctx, future);
if (this instanceof ChannelOutboundHandler) {
throw new IllegalStateException(
"flush(...) must be overridden by " + getClass().getName() +
", which implements " + ChannelOutboundHandler.class.getSimpleName());
}
ctx.flush(future);
}
}

View File

@ -15,7 +15,7 @@
*/
package io.netty.channel;
public class ChannelOutboundByteHandlerAdapter extends ChannelOutboundHandlerAdapter<Byte> {
public abstract class ChannelOutboundByteHandlerAdapter extends ChannelOutboundHandlerAdapter<Byte> {
@Override
public ChannelBufferHolder<Byte> newOutboundBuffer(ChannelHandlerContext ctx) throws Exception {
return ChannelBufferHolders.byteBuffer();

View File

@ -15,8 +15,8 @@
*/
package io.netty.channel;
public abstract class ChannelOutboundHandlerAdapter<O>
extends ChannelOperationHandlerAdapter implements ChannelOutboundHandler<O> {
// Useful when you have to create an anonymous class
@Override
public abstract void flush(ChannelHandlerContext ctx, ChannelFuture future) throws Exception;
}

View File

@ -16,7 +16,7 @@
package io.netty.channel;
public class ChannelOutboundMessageHandlerAdapter<I> extends ChannelOutboundHandlerAdapter<I> {
public abstract class ChannelOutboundMessageHandlerAdapter<I> extends ChannelOutboundHandlerAdapter<I> {
@Override
public ChannelBufferHolder<I> newOutboundBuffer(ChannelHandlerContext ctx) throws Exception {
return ChannelBufferHolders.messageBuffer();

View File

@ -15,9 +15,6 @@
*/
package io.netty.channel;
import io.netty.buffer.ChannelBuffer;
import java.util.Queue;
public class ChannelStateHandlerAdapter implements ChannelStateHandler {
@ -82,28 +79,11 @@ public class ChannelStateHandlerAdapter implements ChannelStateHandler {
@Override
public void inboundBufferUpdated(ChannelHandlerContext ctx) throws Exception {
inboundBufferUpdated0(ctx);
}
static <I> void inboundBufferUpdated0(ChannelHandlerContext ctx) {
if (ctx.hasInboundMessageBuffer()) {
Queue<I> in = ctx.inboundMessageBuffer();
Queue<Object> nextIn = ctx.nextInboundMessageBuffer();
for (;;) {
I msg = in.poll();
if (msg == null) {
break;
}
nextIn.add(msg);
}
} else if (ctx.hasInboundByteBuffer()) {
ChannelBuffer in = ctx.inboundByteBuffer();
ChannelBuffer nextIn = ctx.nextInboundByteBuffer();
nextIn.writeBytes(in);
in.discardReadBytes();
if (this instanceof ChannelInboundHandler) {
throw new IllegalStateException(
"inboundBufferUpdated(...) must be overridden by " + getClass().getName() +
", which implements " + ChannelInboundHandler.class.getSimpleName());
}
ctx.fireInboundBufferUpdated();
}
}