From da04e2cae996492d112cc60ded80d19e07674f42 Mon Sep 17 00:00:00 2001 From: Trustin Lee Date: Thu, 2 Oct 2008 04:40:46 +0000 Subject: [PATCH] Fixed issue: NETTY-54 (Improve SimpleChannelHandler to implement ChannelDownstreamHandler) Fixed issue: NETTY-55 (Channel.unbind() method is missing.) --- .../jboss/netty/channel/AbstractChannel.java | 4 + .../java/org/jboss/netty/channel/Channel.java | 8 ++ .../org/jboss/netty/channel/Channels.java | 33 +++++ .../netty/channel/SimpleChannelHandler.java | 135 ++++++++++++++++-- .../jboss/netty/handler/ssl/SslHandler.java | 4 +- 5 files changed, 172 insertions(+), 12 deletions(-) diff --git a/src/main/java/org/jboss/netty/channel/AbstractChannel.java b/src/main/java/org/jboss/netty/channel/AbstractChannel.java index c62c32e41a..38980a71a1 100644 --- a/src/main/java/org/jboss/netty/channel/AbstractChannel.java +++ b/src/main/java/org/jboss/netty/channel/AbstractChannel.java @@ -150,6 +150,10 @@ public abstract class AbstractChannel implements Channel, Comparable { return Channels.bind(this, localAddress); } + public ChannelFuture unbind() { + return Channels.unbind(this); + } + public ChannelFuture close() { return Channels.close(this); } diff --git a/src/main/java/org/jboss/netty/channel/Channel.java b/src/main/java/org/jboss/netty/channel/Channel.java index 9051e70bd5..f7c7148708 100644 --- a/src/main/java/org/jboss/netty/channel/Channel.java +++ b/src/main/java/org/jboss/netty/channel/Channel.java @@ -220,6 +220,14 @@ public interface Channel { */ ChannelFuture disconnect(); + /** + * Unbinds this channel from the current local address asynchronously. + * + * @return the {@link ChannelFuture} which will be notified when the + * unbind request succeeds or fails + */ + ChannelFuture unbind(); + /** * Closes this channel asynchronously. If this channel is bound or * connected, it will be disconnected and unbound first. diff --git a/src/main/java/org/jboss/netty/channel/Channels.java b/src/main/java/org/jboss/netty/channel/Channels.java index 983cd5444b..3c4ec889e0 100644 --- a/src/main/java/org/jboss/netty/channel/Channels.java +++ b/src/main/java/org/jboss/netty/channel/Channels.java @@ -502,6 +502,39 @@ public class Channels { channel, future, ChannelState.BOUND, localAddress)); } + /** + * Sends a {@code "unbind"} request to the previous + * {@link ChannelDownstreamHandler} in the {@link ChannelPipeline} where + * the specified {@link ChannelHandlerContext} belongs. + * + * @param ctx the context + * @param channel the channel to unbind + * @param future the future which will be notified when the unbind + * operation is done + */ + public static void unbind( + ChannelHandlerContext ctx, Channel channel, ChannelFuture future) { + ctx.sendDownstream(new DefaultChannelStateEvent( + channel, future, ChannelState.BOUND, null)); + } + + /** + * Sends a {@code "unbind"} request to the last + * {@link ChannelDownstreamHandler} in the {@link ChannelPipeline} of + * the specified {@link Channel}. + * + * @param channel the channel to unbind + * + * @return the {@link ChannelFuture} which will be notified when the + * unbind operation is done + */ + public static ChannelFuture unbind(Channel channel) { + ChannelFuture future = future(channel); + channel.getPipeline().sendDownstream(new DefaultChannelStateEvent( + channel, future, ChannelState.BOUND, null)); + return future; + } + /** * Sends a {@code "connect"} request to the last * {@link ChannelDownstreamHandler} in the {@link ChannelPipeline} of diff --git a/src/main/java/org/jboss/netty/channel/SimpleChannelHandler.java b/src/main/java/org/jboss/netty/channel/SimpleChannelHandler.java index fb33ad0c90..e344d87189 100644 --- a/src/main/java/org/jboss/netty/channel/SimpleChannelHandler.java +++ b/src/main/java/org/jboss/netty/channel/SimpleChannelHandler.java @@ -22,24 +22,31 @@ */ package org.jboss.netty.channel; +import java.net.SocketAddress; + import org.jboss.netty.buffer.ChannelBuffer; import org.jboss.netty.logging.InternalLogger; import org.jboss.netty.logging.InternalLoggerFactory; /** - * A {@link ChannelUpstreamHandler} which provides an individual handler method - * for each event type. This handler down-casts the received upstream event - * into more meaningful sub-type event and calls an appropriate handler method - * with the down-cast event. The names of the methods are identical to the - * upstream event names, as introduced in the {@link ChannelUpstreamHandler} - * documentation. + * A {@link ChannelHandler} which provides an individual handler method + * for each event type. This handler down-casts the received upstream or + * or downstream event into more meaningful sub-type event and calls an + * appropriate handler method with the down-cast event. For an upstream + * event, the names of the methods are identical to the upstream event names, + * as introduced in the {@link ChannelUpstreamHandler} documentation. For a + * downstream event, the names of the methods starts with the name of the + * operation and ends with {@code "Requested"} + * (e.g. {@link #writeRequested(ChannelHandlerContext, MessageEvent) writeRequested}.) * - *

Overriding the {@link #handleUpstream(ChannelHandlerContext, ChannelEvent) handleUpstream} method

+ *

Overriding the {@link #handleUpstream(ChannelHandlerContext, ChannelEvent) handleUpstream} + * and {@link #handleDownstream(ChannelHandlerContext, ChannelEvent) handleDownstream} method

*

* You can override the {@link #handleUpstream(ChannelHandlerContext, ChannelEvent) handleUpstream} - * method just like you can do with other {@link ChannelUpstreamHandler}s. - * However, please make sure that you call {@code super.handleUpstream()} so + * and {@link #handleDownstream(ChannelHandlerContext, ChannelEvent) handleDownstream} + * method just like overriding an ordinary Java method. Please make sure to + * call {@code super.handleUpstream()} or {@code super.handleDownstream()} so * that other handler methods are invoked properly: *

*
public class MyChannelHandler extends SimpleChannelHandler {
@@ -53,6 +60,16 @@ import org.jboss.netty.logging.InternalLoggerFactory;
  *
  *         super.handleUpstream(ctx, e);
  *     }
+ *
+ *     public void handleDownstream({@link ChannelHandlerContext} ctx, {@link ChannelEvent} e) throws Exception {
+ *
+ *         // Log all channel state changes.
+ *         if (e instanceof MessageEvent) {
+ *             logger.info("Writing:: " + e);
+ *         }
+ *
+ *         super.handleDownstream(ctx, e);
+ *     }
  * }
* * @author The Netty Project (netty-dev@lists.jboss.org) @@ -60,7 +77,7 @@ import org.jboss.netty.logging.InternalLoggerFactory; * * @version $Rev$, $Date$ */ -public class SimpleChannelHandler implements ChannelUpstreamHandler { +public class SimpleChannelHandler implements ChannelUpstreamHandler, ChannelDownstreamHandler { private static final InternalLogger logger = InternalLoggerFactory.getInstance(SimpleChannelHandler.class.getName()); @@ -116,6 +133,8 @@ public class SimpleChannelHandler implements ChannelUpstreamHandler { case INTEREST_OPS: channelInterestChanged(ctx, evt); break; + default: + ctx.sendDownstream(e); } } else if (e instanceof ExceptionEvent) { exceptionCaught(ctx, (ExceptionEvent) e); @@ -224,4 +243,100 @@ public class SimpleChannelHandler implements ChannelUpstreamHandler { ChannelHandlerContext ctx, ChildChannelStateEvent e) throws Exception { ctx.sendUpstream(e); } + + /** + * {@inheritDoc} Down-casts the received downstream event into more + * meaningful sub-type event and calls an appropriate handler method with + * the down-casted event. + */ + public void handleDownstream(ChannelHandlerContext ctx, ChannelEvent e) + throws Exception { + + if (e instanceof MessageEvent) { + writeRequested(ctx, (MessageEvent) e); + } else if (e instanceof ChannelStateEvent) { + ChannelStateEvent evt = (ChannelStateEvent) e; + switch (evt.getState()) { + case OPEN: + if (!Boolean.TRUE.equals(evt.getValue())) { + closeRequested(ctx, evt); + } + break; + case BOUND: + if (evt.getValue() != null) { + bindRequested(ctx, evt); + } else { + unbindRequested(ctx, evt); + } + break; + case CONNECTED: + if (evt.getValue() != null) { + connectRequested(ctx, evt); + } else { + disconnectRequested(ctx, evt); + } + break; + case INTEREST_OPS: + setInterestOpsRequested(ctx, evt); + break; + default: + ctx.sendDownstream(e); + } + } else { + ctx.sendDownstream(e); + } + } + + /** + * Invoked when {@link Channel#write(Object)} is called. + */ + public void writeRequested(ChannelHandlerContext ctx, MessageEvent e) { + ctx.sendDownstream(e); + } + + /** + * Invoked when {@link Channel#bind(SocketAddress)} was called. + */ + public void bindRequested(ChannelHandlerContext ctx, ChannelStateEvent e) { + ctx.sendDownstream(e); + + } + + /** + * Invoked when {@link Channel#connect(SocketAddress)} was called. + */ + public void connectRequested(ChannelHandlerContext ctx, ChannelStateEvent e) { + ctx.sendDownstream(e); + + } + + /** + * Invoked when {@link Channel#setInterestOps(int)} was called. + */ + public void setInterestOpsRequested(ChannelHandlerContext ctx, ChannelStateEvent e) { + ctx.sendDownstream(e); + } + + /** + * Invoked when {@link Channel#disconnect()} was called. + */ + public void disconnectRequested(ChannelHandlerContext ctx, ChannelStateEvent e) { + ctx.sendDownstream(e); + + } + + /** + * Invoked when {@link Channel#unbind()} was called. + */ + public void unbindRequested(ChannelHandlerContext ctx, ChannelStateEvent e) { + ctx.sendDownstream(e); + + } + + /** + * Invoked when {@link Channel#close()} was called. + */ + public void closeRequested(ChannelHandlerContext ctx, ChannelStateEvent e) { + ctx.sendDownstream(e); + } } diff --git a/src/main/java/org/jboss/netty/handler/ssl/SslHandler.java b/src/main/java/org/jboss/netty/handler/ssl/SslHandler.java index 05e8fa6a33..037471a8e1 100644 --- a/src/main/java/org/jboss/netty/handler/ssl/SslHandler.java +++ b/src/main/java/org/jboss/netty/handler/ssl/SslHandler.java @@ -39,7 +39,6 @@ import javax.net.ssl.SSLEngineResult.Status; import org.jboss.netty.buffer.ChannelBuffer; import org.jboss.netty.buffer.ChannelBuffers; import org.jboss.netty.channel.Channel; -import org.jboss.netty.channel.ChannelDownstreamHandler; import org.jboss.netty.channel.ChannelEvent; import org.jboss.netty.channel.ChannelFuture; import org.jboss.netty.channel.ChannelFutureListener; @@ -96,7 +95,7 @@ import org.jboss.netty.util.ImmediateExecutor; * @apiviz.landmark * @apiviz.uses org.jboss.netty.handler.ssl.SslBufferPool */ -public class SslHandler extends FrameDecoder implements ChannelDownstreamHandler { +public class SslHandler extends FrameDecoder { private static final ByteBuffer EMPTY_BUFFER = ByteBuffer.allocate(0); @@ -293,6 +292,7 @@ public class SslHandler extends FrameDecoder implements ChannelDownstreamHandler return channel.getPipeline().getContext(getClass()); } + @Override public void handleDownstream( final ChannelHandlerContext context, final ChannelEvent evt) throws Exception { if (evt instanceof ChannelStateEvent) {