From ef40ba79417c5e33da6cc626855f50d46713c37f Mon Sep 17 00:00:00 2001 From: Trustin Lee Date: Fri, 12 Jun 2009 08:39:04 +0000 Subject: [PATCH] Added a proxy example which is asked pretty often --- .../netty/example/proxy/HexDumpProxy.java | 72 +++++++++ .../proxy/HexDumpProxyInboundHandler.java | 143 ++++++++++++++++++ .../proxy/HexDumpProxyPipelineFactory.java | 54 +++++++ 3 files changed, 269 insertions(+) create mode 100644 src/main/java/org/jboss/netty/example/proxy/HexDumpProxy.java create mode 100644 src/main/java/org/jboss/netty/example/proxy/HexDumpProxyInboundHandler.java create mode 100644 src/main/java/org/jboss/netty/example/proxy/HexDumpProxyPipelineFactory.java diff --git a/src/main/java/org/jboss/netty/example/proxy/HexDumpProxy.java b/src/main/java/org/jboss/netty/example/proxy/HexDumpProxy.java new file mode 100644 index 0000000000..8dacdae30a --- /dev/null +++ b/src/main/java/org/jboss/netty/example/proxy/HexDumpProxy.java @@ -0,0 +1,72 @@ +/* + * JBoss, Home of Professional Open Source + * + * Copyright 2009, Red Hat Middleware LLC, and individual contributors + * by the @author tags. See the COPYRIGHT.txt in the distribution for a + * full listing of individual contributors. + * + * This is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this software; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA, or see the FSF site: http://www.fsf.org. + */ +package org.jboss.netty.example.proxy; + +import java.net.InetSocketAddress; +import java.util.concurrent.Executor; +import java.util.concurrent.Executors; + +import org.jboss.netty.bootstrap.ServerBootstrap; +import org.jboss.netty.channel.socket.ClientSocketChannelFactory; +import org.jboss.netty.channel.socket.nio.NioClientSocketChannelFactory; +import org.jboss.netty.channel.socket.nio.NioServerSocketChannelFactory; + +/** + * @author The Netty Project (netty-dev@lists.jboss.org) + * @author Trustin Lee (tlee@redhat.com) + * @version $Rev$, $Date$ + */ +public class HexDumpProxy { + + public static void main(String[] args) throws Exception { + // Validate command line options. + if (args.length != 3) { + System.err.println( + "Usage: " + HexDumpProxy.class.getSimpleName() + + " "); + return; + } + + // Parse command line options. + int localPort = Integer.parseInt(args[0]); + String remoteHost = args[1]; + int remotePort = Integer.parseInt(args[2]); + + System.err.println( + "Proxying *:" + localPort + " to " + + remoteHost + ':' + remotePort + " ..."); + + // Configure the bootstrap. + Executor executor = Executors.newCachedThreadPool(); + ServerBootstrap sb = new ServerBootstrap( + new NioServerSocketChannelFactory(executor, executor)); + ClientSocketChannelFactory cf = + new NioClientSocketChannelFactory(executor, executor); + + sb.setPipelineFactory( + new HexDumpProxyPipelineFactory(cf, remoteHost, remotePort)); + + // Start up the server. + sb.bind(new InetSocketAddress(localPort)); + } +} diff --git a/src/main/java/org/jboss/netty/example/proxy/HexDumpProxyInboundHandler.java b/src/main/java/org/jboss/netty/example/proxy/HexDumpProxyInboundHandler.java new file mode 100644 index 0000000000..ba6e4f7df1 --- /dev/null +++ b/src/main/java/org/jboss/netty/example/proxy/HexDumpProxyInboundHandler.java @@ -0,0 +1,143 @@ +/* + * JBoss, Home of Professional Open Source + * + * Copyright 2009, Red Hat Middleware LLC, and individual contributors + * by the @author tags. See the COPYRIGHT.txt in the distribution for a + * full listing of individual contributors. + * + * This is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this software; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA, or see the FSF site: http://www.fsf.org. + */ +package org.jboss.netty.example.proxy; + +import java.net.InetSocketAddress; + +import org.jboss.netty.bootstrap.ClientBootstrap; +import org.jboss.netty.buffer.ChannelBuffer; +import org.jboss.netty.buffer.ChannelBuffers; +import org.jboss.netty.channel.Channel; +import org.jboss.netty.channel.ChannelFuture; +import org.jboss.netty.channel.ChannelFutureListener; +import org.jboss.netty.channel.ChannelHandlerContext; +import org.jboss.netty.channel.ChannelPipelineCoverage; +import org.jboss.netty.channel.ChannelStateEvent; +import org.jboss.netty.channel.ExceptionEvent; +import org.jboss.netty.channel.MessageEvent; +import org.jboss.netty.channel.SimpleChannelUpstreamHandler; +import org.jboss.netty.channel.socket.ClientSocketChannelFactory; + +/** + * @author The Netty Project (netty-dev@lists.jboss.org) + * @author Trustin Lee (tlee@redhat.com) + * @version $Rev$, $Date$ + */ +@ChannelPipelineCoverage("one") +public class HexDumpProxyInboundHandler extends SimpleChannelUpstreamHandler { + + private final ClientSocketChannelFactory cf; + private final String remoteHost; + private final int remotePort; + + private volatile Channel outboundChannel; + + public HexDumpProxyInboundHandler( + ClientSocketChannelFactory cf, String remoteHost, int remotePort) { + this.cf = cf; + this.remoteHost = remoteHost; + this.remotePort = remotePort; + } + + @Override + public void channelOpen(ChannelHandlerContext ctx, ChannelStateEvent e) + throws Exception { + // Suspend incoming traffic until connected to the remote host. + final Channel inboundChannel = e.getChannel(); + inboundChannel.setReadable(false); + + // Start the connection attempt. + ClientBootstrap cb = new ClientBootstrap(cf); + cb.getPipeline().addLast("handler", new OutboundHandler(e.getChannel())); + ChannelFuture f = cb.connect(new InetSocketAddress(remoteHost, remotePort)); + + outboundChannel = f.getChannel(); + f.addListener(new ChannelFutureListener() { + public void operationComplete(ChannelFuture future) throws Exception { + if (future.isSuccess()) { + // Connection attempt succeeded: + // Begin to accept incoming traffic. + inboundChannel.setReadable(true); + } else { + // Close the connection if the connection attempt has failed. + future.getChannel().close(); + } + } + }); + } + + @Override + public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) + throws Exception { + ChannelBuffer msg = (ChannelBuffer) e.getMessage(); + System.out.println(">>> " + ChannelBuffers.hexDump(msg)); + outboundChannel.write(msg); + } + + @Override + public void channelClosed(ChannelHandlerContext ctx, ChannelStateEvent e) + throws Exception { + if (outboundChannel != null) { + outboundChannel.close(); + } + } + + @Override + public void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent e) + throws Exception { + e.getCause().printStackTrace(); + e.getChannel().close(); + } + + @ChannelPipelineCoverage("one") + private class OutboundHandler extends SimpleChannelUpstreamHandler { + + private final Channel inboundChannel; + + OutboundHandler(Channel inboundChannel) { + this.inboundChannel = inboundChannel; + } + + @Override + public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) + throws Exception { + ChannelBuffer msg = (ChannelBuffer) e.getMessage(); + System.out.println("<<< " + ChannelBuffers.hexDump(msg)); + inboundChannel.write(msg); + } + + @Override + public void channelClosed(ChannelHandlerContext ctx, ChannelStateEvent e) + throws Exception { + inboundChannel.close(); + } + + @Override + public void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent e) + throws Exception { + e.getCause().printStackTrace(); + e.getChannel().close(); + } + } + +} diff --git a/src/main/java/org/jboss/netty/example/proxy/HexDumpProxyPipelineFactory.java b/src/main/java/org/jboss/netty/example/proxy/HexDumpProxyPipelineFactory.java new file mode 100644 index 0000000000..17897cb542 --- /dev/null +++ b/src/main/java/org/jboss/netty/example/proxy/HexDumpProxyPipelineFactory.java @@ -0,0 +1,54 @@ +/* + * JBoss, Home of Professional Open Source + * + * Copyright 2009, Red Hat Middleware LLC, and individual contributors + * by the @author tags. See the COPYRIGHT.txt in the distribution for a + * full listing of individual contributors. + * + * This is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this software; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA, or see the FSF site: http://www.fsf.org. + */ +package org.jboss.netty.example.proxy; + +import static org.jboss.netty.channel.Channels.*; + +import org.jboss.netty.channel.ChannelPipeline; +import org.jboss.netty.channel.ChannelPipelineFactory; +import org.jboss.netty.channel.socket.ClientSocketChannelFactory; + +/** + * @author The Netty Project (netty-dev@lists.jboss.org) + * @author Trustin Lee (tlee@redhat.com) + * @version $Rev$, $Date$ + */ +public class HexDumpProxyPipelineFactory implements ChannelPipelineFactory { + + private final ClientSocketChannelFactory cf; + private final String remoteHost; + private final int remotePort; + + public HexDumpProxyPipelineFactory( + ClientSocketChannelFactory cf, String remoteHost, int remotePort) { + this.cf = cf; + this.remoteHost = remoteHost; + this.remotePort = remotePort; + } + + public ChannelPipeline getPipeline() throws Exception { + ChannelPipeline p = pipeline(); // Note the static import. + p.addLast("handler", new HexDumpProxyInboundHandler(cf, remoteHost, remotePort)); + return p; + } +}