Package com.dianping.dproxy.socks

Source Code of com.dianping.dproxy.socks.SocksServerConnectHandler

package com.dianping.dproxy.socks;

import org.jboss.netty.bootstrap.ClientBootstrap;
import org.jboss.netty.buffer.ChannelBuffer;
import org.jboss.netty.buffer.ChannelBuffers;
import org.jboss.netty.channel.*;
import org.jboss.netty.channel.socket.ClientSocketChannelFactory;
import org.jboss.netty.handler.codec.socks.SocksCmdRequest;
import org.jboss.netty.handler.codec.socks.SocksCmdResponse;
import org.jboss.netty.handler.codec.socks.SocksMessage;

import java.net.InetSocketAddress;

/**
* @author yihua.huang@dianping.com
*/
public class SocksServerConnectHandler extends SimpleChannelUpstreamHandler {

  private static final String name = "SOCKS_SERVER_CONNECT_HANDLER";

  public static String getName() {
    return name;
  }

  private final ClientSocketChannelFactory cf;

  private volatile Channel outboundChannel;

  final Object trafficLock = new Object();

  public SocksServerConnectHandler(ClientSocketChannelFactory cf) {
    this.cf = cf;
  }

  @Override
  public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) throws Exception {
    final SocksCmdRequest socksCmdRequest = (SocksCmdRequest) e.getMessage();
    final Channel inboundChannel = e.getChannel();
    inboundChannel.setReadable(false);

    // Start the connection attempt.
    final ClientBootstrap cb = new ClientBootstrap(cf);
    cb.setOption("keepAlive", true);
    cb.setOption("tcpNoDelay", true);
    cb.setPipelineFactory(new ChannelPipelineFactory() {
      @Override
      public ChannelPipeline getPipeline() throws Exception {
        ChannelPipeline pipeline = Channels.pipeline();
        // 外部server数据转发到client
        pipeline.addLast("outboundChannel", new OutboundHandler(inboundChannel, "out"));
        return pipeline;
      }
    });

    ChannelFuture f = cb.connect(new InetSocketAddress(socksCmdRequest.getHost(), socksCmdRequest.getPort()));

    outboundChannel = f.getChannel();
    ctx.getPipeline().remove(getName());
    f.addListener(new ChannelFutureListener() {
      public void operationComplete(ChannelFuture future) throws Exception {
        if (future.isSuccess()) {
          // client数据转发到外部server
          inboundChannel.getPipeline().addLast("inboundChannel", new OutboundHandler(outboundChannel, "in"));
          inboundChannel.write(new SocksCmdResponse(SocksMessage.CmdStatus.SUCCESS, socksCmdRequest
              .getAddressType()));
          inboundChannel.setReadable(true);
        } else {
          inboundChannel.write(new SocksCmdResponse(SocksMessage.CmdStatus.FAILURE, socksCmdRequest
              .getAddressType()));
          inboundChannel.close();
        }
      }
    });
  }

  @Override
  public void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent e) throws Exception {
    super.exceptionCaught(ctx, e);
  }

  private class OutboundHandler extends SimpleChannelUpstreamHandler {

    private final Channel inboundChannel;

    private String name;

    OutboundHandler(Channel inboundChannel, String name) {
      this.inboundChannel = inboundChannel;
      this.name = name;
    }

    @Override
    public void messageReceived(ChannelHandlerContext ctx, final MessageEvent e) throws Exception {
      final ChannelBuffer msg = (ChannelBuffer) e.getMessage();
      synchronized (trafficLock) {
        inboundChannel.write(msg);

      }
    }

    @Override
    public void channelClosed(ChannelHandlerContext ctx, ChannelStateEvent e) throws Exception {
      closeOnFlush(inboundChannel);
    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent e) throws Exception {
      e.getCause().printStackTrace();
      closeOnFlush(e.getChannel());
    }
  }

  /**
   * Closes the specified channel after all queued write requests are flushed.
   */
  static void closeOnFlush(Channel ch) {
    if (ch.isConnected()) {
      ch.write(ChannelBuffers.EMPTY_BUFFER).addListener(ChannelFutureListener.CLOSE);
    }
  }
}
TOP

Related Classes of com.dianping.dproxy.socks.SocksServerConnectHandler

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.