@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().
| Modifier and Type | Field and Description |
|---|---|
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.
|
| Modifier and Type | Method and Description |
|---|---|
static InetSocketAddress |
addressFor(String hostAndPort,
DefaultHttpProxyServer proxyServer)
Build an
InetSocketAddress for the given hostAndPort. |
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()
Callback that's invoked if this connection becomes saturated.
|
protected void |
becameWritable()
Callback that's invoked when this connection becomes writeable again.
|
protected void |
become(org.littleshoot.proxy.impl.ConnectionState newState)
Lifecycle
|
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 when the connection to the server or upstream chained proxy fails.
|
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() |
protected HttpFilters |
getHttpFiltersFromProxyServer(io.netty.handler.codec.http.HttpRequest httpRequest)
Request the ProxyServer for Filters.
|
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) |
acceptInboundMessage, channelReadchannelReadComplete, channelUnregisteredhandlerAdded, handlerRemoved, isSharableprotected final org.littleshoot.proxy.impl.ProxyConnectionLogger LOG
protected final DefaultHttpProxyServer proxyServer
protected final boolean runsAsSslClient
protected volatile io.netty.channel.ChannelHandlerContext ctx
protected volatile io.netty.channel.Channel channel
protected volatile long lastReadTime
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.
protected void read(Object msg)
protected org.littleshoot.proxy.impl.ConnectionState readHTTPInitial(io.netty.handler.codec.http.HttpResponse httpResponse)
HttpRequest or HttpResponse).protected void readHTTPChunk(io.netty.handler.codec.http.HttpContent chunk)
protected void readRaw(io.netty.buffer.ByteBuf buf)
protected void writeHttp(io.netty.handler.codec.http.HttpObject httpObject)
protected void become(org.littleshoot.proxy.impl.ConnectionState newState)
protected void becameSaturated()
protected void becameWritable()
protected void timedOut()
Channel times out due
to an idle timeout.protected void disconnected()
Channel becomes
disconnected.protected void exceptionCaught(Throwable cause)
Channel.public TransportProtocol getTransportProtocol()
public InetSocketAddress getRemoteAddress()
public String getServerHostAndPort()
public boolean hasUpstreamChainedProxy()
public InetSocketAddress getChainedProxyAddress()
public ChainedProxy getChainedProxy()
public io.netty.handler.codec.http.HttpRequest getInitialRequest()
protected HttpFilters getHttpFiltersFromProxyServer(io.netty.handler.codec.http.HttpRequest httpRequest)
httpRequest - Filter attached to the give HttpRequest (if any)protected boolean connectionFailed(Throwable cause) throws UnknownHostException
cause - the reason that our attempt to connect failed (can be null)UnknownHostExceptionpublic static InetSocketAddress addressFor(String hostAndPort, DefaultHttpProxyServer proxyServer) throws UnknownHostException
InetSocketAddress for the given hostAndPort.hostAndPort - String representation of the host and portproxyServer - the current DefaultHttpProxyServerUnknownHostException - if hostAndPort could not be resolved, or if the input string could not be parsed into
a host and port.protected void writeRaw(io.netty.buffer.ByteBuf buf)
buf - protected io.netty.channel.ChannelFuture writeToChannel(Object msg)
protected void connected()
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.protected io.netty.util.concurrent.Future<io.netty.channel.Channel> encrypt(SSLEngine sslEngine, boolean authenticateClients)
sslEngine - the SSLEngine for doing the encryptionauthenticateClients - determines whether to authenticate clients or notprotected io.netty.util.concurrent.Future<io.netty.channel.Channel> encrypt(io.netty.channel.ChannelPipeline pipeline,
SSLEngine sslEngine,
boolean authenticateClients)
pipeline - the ChannelPipeline on which to enable encryptionsslEngine - the SSLEngine for doing the encryptionauthenticateClients - determines whether to authenticate clients or notprotected org.littleshoot.proxy.impl.ConnectionFlowStep EncryptChannel(SSLEngine sslEngine)
SSLEngine.sslEngine - the SSLEngine for doing the encryptionprotected void aggregateContentForFiltering(io.netty.channel.ChannelPipeline pipeline,
int numberOfBytesToBuffer)
pipeline - numberOfBytesToBuffer - protected boolean isSaturated()
protected boolean is(org.littleshoot.proxy.impl.ConnectionState state)
state - protected boolean isConnecting()
ConnectionFlow, this will return true.protected org.littleshoot.proxy.impl.ConnectionState getCurrentState()
public boolean isTunneling()
public SSLEngine getSslEngine()
protected void stopReading()
protected void resumeReading()
protected final void channelRead0(io.netty.channel.ChannelHandlerContext ctx,
Object msg)
throws Exception
public void channelRegistered(io.netty.channel.ChannelHandlerContext ctx)
throws Exception
channelRegistered in interface io.netty.channel.ChannelInboundHandlerchannelRegistered in class io.netty.channel.ChannelInboundHandlerAdapterExceptionpublic final void channelActive(io.netty.channel.ChannelHandlerContext ctx)
throws Exception
channelActive in interface io.netty.channel.ChannelInboundHandlerchannelActive in class io.netty.channel.ChannelInboundHandlerAdapterExceptionpublic void channelInactive(io.netty.channel.ChannelHandlerContext ctx)
throws Exception
channelInactive in interface io.netty.channel.ChannelInboundHandlerchannelInactive in class io.netty.channel.ChannelInboundHandlerAdapterExceptionpublic final void channelWritabilityChanged(io.netty.channel.ChannelHandlerContext ctx)
throws Exception
channelWritabilityChanged in interface io.netty.channel.ChannelInboundHandlerchannelWritabilityChanged in class io.netty.channel.ChannelInboundHandlerAdapterExceptionpublic final void exceptionCaught(io.netty.channel.ChannelHandlerContext ctx,
Throwable cause)
throws Exception
exceptionCaught in interface io.netty.channel.ChannelHandlerexceptionCaught in interface io.netty.channel.ChannelInboundHandlerexceptionCaught in class io.netty.channel.ChannelInboundHandlerAdapterExceptionpublic 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.
userEventTriggered in interface io.netty.channel.ChannelInboundHandleruserEventTriggered in class io.netty.channel.ChannelInboundHandlerAdapterExceptionCopyright © 2009–2016 LittleShoot. All rights reserved.