org.littleshoot.proxy.impl
Class ProxyToServerConnection

java.lang.Object
  extended by io.netty.channel.ChannelHandlerAdapter
      extended by io.netty.channel.ChannelInboundHandlerAdapter
          extended by io.netty.channel.SimpleChannelInboundHandler<Object>
              extended by org.littleshoot.proxy.impl.ProxyToServerConnection
All Implemented Interfaces:
io.netty.channel.ChannelHandler, io.netty.channel.ChannelInboundHandler

@ChannelHandler.Sharable
public class ProxyToServerConnection
extends io.netty.channel.SimpleChannelInboundHandler<Object>

Represents a connection from our proxy to a server on the web. ProxyConnections are reused fairly liberally, and can go from disconnected to connected, back to disconnected and so on.

Connecting a ProxyToServerConnection can involve more than just connecting the underlying Channel. In particular, the connection may use encryption (i.e. TLS) and it may also establish an HTTP CONNECT tunnel. The various steps involved in fully establishing a connection are encapsulated in the property connectionFlow, which is initialized in initializeConnectionFlow().


Nested Class Summary
 
Nested classes/interfaces inherited from interface io.netty.channel.ChannelHandler
io.netty.channel.ChannelHandler.Sharable
 
Field Summary
protected  io.netty.channel.Channel channel
           
protected  io.netty.channel.ChannelHandlerContext ctx
           
protected  long lastReadTime
           
protected  org.littleshoot.proxy.impl.ProxyConnectionLogger LOG
           
protected  DefaultHttpProxyServer proxyServer
           
protected  boolean runsAsSslClient
           
protected  SSLEngine sslEngine
          If using encryption, this holds our SSLEngine.
protected  org.littleshoot.proxy.impl.ConnectionFlowStep StartTunneling
           Enables tunneling on this connection by dropping the HTTP related encoders and decoders, as well as idle timers.
 
Method Summary
protected  void aggregateContentForFiltering(io.netty.channel.ChannelPipeline pipeline, int numberOfBytesToBuffer)
          Enables decompression and aggregation of content, which is useful for certain types of filtering activity.
protected  void becameSaturated()
          Lifecycle
protected  void becameWritable()
          Callback that's invoked when this connection becomes writeable again.
protected  void become(org.littleshoot.proxy.impl.ConnectionState state)
          Udpates the current state to the given value.
 void channelActive(io.netty.channel.ChannelHandlerContext ctx)
          Only once the Netty Channel is active to we recognize the ProxyConnection as connected.
 void channelInactive(io.netty.channel.ChannelHandlerContext ctx)
          As soon as the Netty Channel is inactive, we recognize the ProxyConnection as disconnected.
protected  void channelRead0(io.netty.channel.ChannelHandlerContext ctx, Object msg)
          Adapting the Netty API
 void channelRegistered(io.netty.channel.ChannelHandlerContext ctx)
           
 void channelWritabilityChanged(io.netty.channel.ChannelHandlerContext ctx)
           
protected  void connected()
          This method is called as soon as the underlying Channel is connected.
protected  boolean connectionFailed(Throwable cause)
           Called to let us know that connection failed.
protected  void disconnected()
          This method is called as soon as the underlying Channel becomes disconnected.
protected  io.netty.util.concurrent.Future<io.netty.channel.Channel> encrypt(io.netty.channel.ChannelPipeline pipeline, SSLEngine sslEngine, boolean authenticateClients)
          Encrypts traffic on this connection with SSL/TLS.
protected  io.netty.util.concurrent.Future<io.netty.channel.Channel> encrypt(SSLEngine sslEngine, boolean authenticateClients)
          Encrypts traffic on this connection with SSL/TLS.
protected  org.littleshoot.proxy.impl.ConnectionFlowStep EncryptChannel(SSLEngine sslEngine)
          Encrypts the channel using the provided SSLEngine.
 void exceptionCaught(io.netty.channel.ChannelHandlerContext ctx, Throwable cause)
           
protected  void exceptionCaught(Throwable cause)
          Override this to handle exceptions that occurred during asynchronous processing on the Channel.
 ChainedProxy getChainedProxy()
           
 InetSocketAddress getChainedProxyAddress()
           
protected  org.littleshoot.proxy.impl.ConnectionState getCurrentState()
           
 io.netty.handler.codec.http.HttpRequest getInitialRequest()
           
 InetSocketAddress getRemoteAddress()
           
 String getServerHostAndPort()
           
 SSLEngine getSslEngine()
           
 TransportProtocol getTransportProtocol()
          State Management
 boolean hasUpstreamChainedProxy()
           
protected  boolean is(org.littleshoot.proxy.impl.ConnectionState state)
          Utility for checking current state.
protected  boolean isConnecting()
          If this connection is currently in the process of going through a ConnectionFlow, this will return true.
protected  boolean isSaturated()
          Indicates whether or not this connection is saturated (i.e.
 boolean isTunneling()
           
protected  void read(Object msg)
          Reading
protected  void readHTTPChunk(io.netty.handler.codec.http.HttpContent chunk)
          Implement this to handle reading a chunk in a chunked transfer.
protected  org.littleshoot.proxy.impl.ConnectionState readHTTPInitial(io.netty.handler.codec.http.HttpResponse httpResponse)
          Implement this to handle reading the initial object (e.g.
protected  void readRaw(io.netty.buffer.ByteBuf buf)
          Implement this to handle reading a raw buffer as they are used in HTTP tunneling.
protected  void resumeReading()
          Call this to resume reading.
protected  void stopReading()
          Call this to stop reading.
protected  void timedOut()
          This method is called when the underlying Channel times out due to an idle timeout.
 void userEventTriggered(io.netty.channel.ChannelHandlerContext ctx, Object evt)
           We're looking for IdleStateEvents to see if we need to disconnect.
protected  void writeHttp(io.netty.handler.codec.http.HttpObject httpObject)
          Writes HttpObjects to the connection asynchronously.
protected  void writeRaw(io.netty.buffer.ByteBuf buf)
          Writes raw buffers to the connection.
protected  io.netty.channel.ChannelFuture writeToChannel(Object msg)
           
 
Methods inherited from class io.netty.channel.SimpleChannelInboundHandler
acceptInboundMessage, channelRead
 
Methods inherited from class io.netty.channel.ChannelInboundHandlerAdapter
channelReadComplete, channelUnregistered
 
Methods inherited from class io.netty.channel.ChannelHandlerAdapter
handlerAdded, handlerRemoved, isSharable
 
Methods inherited from class java.lang.Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
 
Methods inherited from interface io.netty.channel.ChannelHandler
handlerAdded, handlerRemoved
 

Field Detail

LOG

protected final org.littleshoot.proxy.impl.ProxyConnectionLogger LOG

proxyServer

protected final DefaultHttpProxyServer proxyServer

runsAsSslClient

protected final boolean runsAsSslClient

ctx

protected volatile io.netty.channel.ChannelHandlerContext ctx

channel

protected volatile io.netty.channel.Channel channel

lastReadTime

protected volatile long lastReadTime

sslEngine

protected volatile SSLEngine sslEngine
If using encryption, this holds our SSLEngine.


StartTunneling

protected org.littleshoot.proxy.impl.ConnectionFlowStep StartTunneling

Enables tunneling on this connection by dropping the HTTP related encoders and decoders, as well as idle timers.

Note - the work is done on the ChannelHandlerContext's executor because ChannelPipeline.remove(String) can deadlock if called directly.

Method Detail

read

protected void read(Object msg)
Reading


readHTTPInitial

protected org.littleshoot.proxy.impl.ConnectionState readHTTPInitial(io.netty.handler.codec.http.HttpResponse httpResponse)
Implement this to handle reading the initial object (e.g. HttpRequest or HttpResponse).

Returns:

readHTTPChunk

protected void readHTTPChunk(io.netty.handler.codec.http.HttpContent chunk)
Implement this to handle reading a chunk in a chunked transfer.


readRaw

protected void readRaw(io.netty.buffer.ByteBuf buf)
Implement this to handle reading a raw buffer as they are used in HTTP tunneling.


writeHttp

protected void writeHttp(io.netty.handler.codec.http.HttpObject httpObject)
Writes HttpObjects to the connection asynchronously.


becameSaturated

protected void becameSaturated()
Lifecycle


becameWritable

protected void becameWritable()
Callback that's invoked when this connection becomes writeable again.


timedOut

protected void timedOut()
This method is called when the underlying Channel times out due to an idle timeout.


disconnected

protected void disconnected()
This method is called as soon as the underlying Channel becomes disconnected.


exceptionCaught

protected void exceptionCaught(Throwable cause)
Override this to handle exceptions that occurred during asynchronous processing on the Channel.


getTransportProtocol

public TransportProtocol getTransportProtocol()
State Management


getRemoteAddress

public InetSocketAddress getRemoteAddress()

getServerHostAndPort

public String getServerHostAndPort()

hasUpstreamChainedProxy

public boolean hasUpstreamChainedProxy()

getChainedProxyAddress

public InetSocketAddress getChainedProxyAddress()

getChainedProxy

public ChainedProxy getChainedProxy()

getInitialRequest

public io.netty.handler.codec.http.HttpRequest getInitialRequest()

connectionFailed

protected boolean connectionFailed(Throwable cause)
                            throws UnknownHostException

Called to let us know that connection failed.

Try connecting to a new address, using a new set of connection parameters.

Parameters:
cause - the reason that our attempt to connect failed (can be null)
Returns:
true if we are trying to fall back to another connection
Throws:
UnknownHostException

writeRaw

protected void writeRaw(io.netty.buffer.ByteBuf buf)
Writes raw buffers to the connection.

Parameters:
buf -

writeToChannel

protected io.netty.channel.ChannelFuture writeToChannel(Object msg)

connected

protected void connected()
This method is called as soon as the underlying Channel is connected. Note that for proxies with complex ConnectionFlows that include SSL handshaking and other such things, just because the Channel is connected doesn't mean that our connection is fully established.


encrypt

protected io.netty.util.concurrent.Future<io.netty.channel.Channel> encrypt(SSLEngine sslEngine,
                                                                            boolean authenticateClients)
Encrypts traffic on this connection with SSL/TLS.

Parameters:
sslEngine - the SSLEngine for doing the encryption
authenticateClients - determines whether to authenticate clients or not
Returns:
a Future for when the SSL handshake has completed

encrypt

protected io.netty.util.concurrent.Future<io.netty.channel.Channel> encrypt(io.netty.channel.ChannelPipeline pipeline,
                                                                            SSLEngine sslEngine,
                                                                            boolean authenticateClients)
Encrypts traffic on this connection with SSL/TLS.

Parameters:
pipeline - the ChannelPipeline on which to enable encryption
sslEngine - the SSLEngine for doing the encryption
authenticateClients - determines whether to authenticate clients or not
Returns:
a Future for when the SSL handshake has completed

EncryptChannel

protected org.littleshoot.proxy.impl.ConnectionFlowStep EncryptChannel(SSLEngine sslEngine)
Encrypts the channel using the provided SSLEngine.

Parameters:
sslEngine - the SSLEngine for doing the encryption

aggregateContentForFiltering

protected void aggregateContentForFiltering(io.netty.channel.ChannelPipeline pipeline,
                                            int numberOfBytesToBuffer)
Enables decompression and aggregation of content, which is useful for certain types of filtering activity.

Parameters:
pipeline -
numberOfBytesToBuffer -

isSaturated

protected boolean isSaturated()
Indicates whether or not this connection is saturated (i.e. not writeable).

Returns:

is

protected boolean is(org.littleshoot.proxy.impl.ConnectionState state)
Utility for checking current state.

Parameters:
state -
Returns:

isConnecting

protected boolean isConnecting()
If this connection is currently in the process of going through a ConnectionFlow, this will return true.

Returns:

become

protected void become(org.littleshoot.proxy.impl.ConnectionState state)
Udpates the current state to the given value.

Parameters:
state -

getCurrentState

protected org.littleshoot.proxy.impl.ConnectionState getCurrentState()

isTunneling

public boolean isTunneling()

getSslEngine

public SSLEngine getSslEngine()

stopReading

protected void stopReading()
Call this to stop reading.


resumeReading

protected void resumeReading()
Call this to resume reading.


channelRead0

protected final void channelRead0(io.netty.channel.ChannelHandlerContext ctx,
                                  Object msg)
                           throws Exception
Adapting the Netty API

Specified by:
channelRead0 in class io.netty.channel.SimpleChannelInboundHandler<Object>
Throws:
Exception

channelRegistered

public void channelRegistered(io.netty.channel.ChannelHandlerContext ctx)
                       throws Exception
Specified by:
channelRegistered in interface io.netty.channel.ChannelInboundHandler
Overrides:
channelRegistered in class io.netty.channel.ChannelInboundHandlerAdapter
Throws:
Exception

channelActive

public final void channelActive(io.netty.channel.ChannelHandlerContext ctx)
                         throws Exception
Only once the Netty Channel is active to we recognize the ProxyConnection as connected.

Specified by:
channelActive in interface io.netty.channel.ChannelInboundHandler
Overrides:
channelActive in class io.netty.channel.ChannelInboundHandlerAdapter
Throws:
Exception

channelInactive

public void channelInactive(io.netty.channel.ChannelHandlerContext ctx)
                     throws Exception
As soon as the Netty Channel is inactive, we recognize the ProxyConnection as disconnected.

Specified by:
channelInactive in interface io.netty.channel.ChannelInboundHandler
Overrides:
channelInactive in class io.netty.channel.ChannelInboundHandlerAdapter
Throws:
Exception

channelWritabilityChanged

public final void channelWritabilityChanged(io.netty.channel.ChannelHandlerContext ctx)
                                     throws Exception
Specified by:
channelWritabilityChanged in interface io.netty.channel.ChannelInboundHandler
Overrides:
channelWritabilityChanged in class io.netty.channel.ChannelInboundHandlerAdapter
Throws:
Exception

exceptionCaught

public final void exceptionCaught(io.netty.channel.ChannelHandlerContext ctx,
                                  Throwable cause)
                           throws Exception
Specified by:
exceptionCaught in interface io.netty.channel.ChannelHandler
Specified by:
exceptionCaught in interface io.netty.channel.ChannelInboundHandler
Overrides:
exceptionCaught in class io.netty.channel.ChannelInboundHandlerAdapter
Throws:
Exception

userEventTriggered

public final void userEventTriggered(io.netty.channel.ChannelHandlerContext ctx,
                                     Object evt)
                              throws Exception

We're looking for IdleStateEvents to see if we need to disconnect.

Note - we don't care what kind of IdleState we got. Thanks to qbast for pointing this out.

Specified by:
userEventTriggered in interface io.netty.channel.ChannelInboundHandler
Overrides:
userEventTriggered in class io.netty.channel.ChannelInboundHandlerAdapter
Throws:
Exception


Copyright © 2009-2014 LittleShoot. All Rights Reserved.