@ChannelHandler.Sharable public class ProxyToServerConnection extends ProxyConnection<io.netty.handler.codec.http.HttpResponse>
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 | Class and Description |
---|---|
private class |
ProxyToServerConnection.HeadAwareHttpResponseDecoder
Responses to HEAD requests aren't supposed to have content, but Netty
doesn't know that any given response is to a HEAD request, so it needs to
be told that there's no content so that it doesn't hang waiting for it.
|
ProxyConnection.BytesReadMonitor, ProxyConnection.BytesWrittenMonitor, ProxyConnection.RequestReadMonitor, ProxyConnection.RequestWrittenMonitor, ProxyConnection.ResponseReadMonitor, ProxyConnection.ResponseWrittenMonitor
Modifier and Type | Field and Description |
---|---|
private Queue<ChainedProxy> |
availableChainedProxies |
private ProxyConnection.BytesReadMonitor |
bytesReadMonitor
Activity Tracking/Statistics
We track statistics on bytes, requests and responses by adding handlers
at the appropriate parts of the pipeline (see initChannelPipeline()).
|
private ProxyConnection.BytesWrittenMonitor |
bytesWrittenMonitor |
private ChainedProxy |
chainedProxy |
private ClientToProxyConnection |
clientConnection |
private ConnectionFlowStep |
ConnectChannel
Opens the socket connection.
|
private ConnectionFlow |
connectionFlow
Encapsulates the flow for establishing a connection, which can vary
depending on how things are configured.
|
private Object |
connectLock
While we're in the process of connecting, it's possible that we'll
receive a new message to write.
|
private HttpFilters |
currentFilters
The filters to apply to response/chunks received from server.
|
private io.netty.handler.codec.http.HttpRequest |
currentHttpRequest
While we're doing a chunked transfer, this keeps track of the HttpRequest
to which we're responding.
|
private io.netty.handler.codec.http.HttpResponse |
currentHttpResponse
While we're doing a chunked transfer, this keeps track of the initial
HttpResponse object for our transfer (which is useful for its headers).
|
private boolean |
disableSni
Disables SNI when initializing connection flow in
initializeConnectionFlow() . |
private ConnectionFlowStep |
HTTPCONNECTWithChainedProxy
Writes the HTTP CONNECT to the server and waits for a 200 response.
|
private io.netty.handler.codec.http.HttpRequest |
initialRequest
This is the initial request received prior to connecting.
|
private Queue<io.netty.handler.codec.http.HttpRequest> |
issuedRequests
Keeps track of HttpRequests that have been issued so that we can
associate them with responses that we get back
|
private InetSocketAddress |
localAddress |
private static int |
MINIMUM_RECV_BUFFER_SIZE_BYTES
Minimum size of the adaptive recv buffer when throttling is enabled.
|
private ConnectionFlowStep |
MitmEncryptClientChannel
Encrypts the client channel based on our server
SSLSession . |
private InetSocketAddress |
remoteAddress |
private ProxyConnection.RequestWrittenMonitor |
requestWrittenMonitor |
private ProxyConnection.ResponseReadMonitor |
responseReadMonitor |
private ProxyToServerConnection |
serverConnection |
private String |
serverHostAndPort |
private io.netty.handler.traffic.GlobalTrafficShapingHandler |
trafficHandler
Limits bandwidth when throttling is enabled.
|
private TransportProtocol |
transportProtocol |
channel, ctx, lastReadTime, LOG, proxyServer, runsAsSslClient, sslEngine, StartTunneling
Modifier | Constructor and Description |
---|---|
private |
ProxyToServerConnection(DefaultHttpProxyServer proxyServer,
ClientToProxyConnection clientConnection,
String serverHostAndPort,
ChainedProxy chainedProxy,
Queue<ChainedProxy> availableChainedProxies,
HttpFilters initialFilters,
io.netty.handler.traffic.GlobalTrafficShapingHandler globalTrafficShapingHandler) |
Modifier and Type | Method and Description |
---|---|
static InetSocketAddress |
addressFor(String hostAndPort,
DefaultHttpProxyServer proxyServer)
Build an
InetSocketAddress for the given hostAndPort. |
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(ConnectionState newState)
Lifecycle
|
private void |
connectAndWrite(io.netty.handler.codec.http.HttpRequest initialRequest)
Configures the connection to the upstream server and begins the
ConnectionFlow . |
protected boolean |
connectionFailed(Throwable cause)
Called when the connection to the server or upstream chained proxy fails.
|
(package private) void |
connectionSucceeded(boolean shouldForwardInitialRequest)
Do all the stuff that needs to be done after our
ConnectionFlow
has succeeded. |
(package private) static ProxyToServerConnection |
create(DefaultHttpProxyServer proxyServer,
ClientToProxyConnection clientConnection,
String serverHostAndPort,
HttpFilters initialFilters,
io.netty.handler.codec.http.HttpRequest initialHttpRequest,
io.netty.handler.traffic.GlobalTrafficShapingHandler globalTrafficShapingHandler)
Create a new ProxyToServerConnection.
|
protected void |
disconnected()
This method is called as soon as the underlying
Channel becomes
disconnected. |
protected void |
exceptionCaught(Throwable cause)
Override this to handle exceptions that occurred during asynchronous
processing on the
Channel . |
ChainedProxy |
getChainedProxy() |
InetSocketAddress |
getChainedProxyAddress() |
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() |
TransportProtocol |
getTransportProtocol()
State Management
|
boolean |
hasUpstreamChainedProxy() |
private void |
identifyCurrentRequest()
An HTTP response is associated with a single request, so we can pop the
correct request off the queue.
|
private void |
initChannelPipeline(io.netty.channel.ChannelPipeline pipeline,
io.netty.handler.codec.http.HttpRequest httpRequest)
Initialize our
ChannelPipeline . |
private void |
initializeConnectionFlow()
This method initializes our
ConnectionFlow based on however this connection has been configured. |
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 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.
|
private void |
rememberCurrentResponse(io.netty.handler.codec.http.HttpResponse response)
Keeps track of the current HttpResponse so that we can associate its
headers with future related chunks for this same transfer.
|
private void |
resetConnectionForRetry()
Convenience method to prepare to retry this connection.
|
private void |
respondWith(io.netty.handler.codec.http.HttpObject httpObject)
Respond to the client with the given
HttpObject . |
private void |
setupConnectionParameters()
Set up our connection parameters based on server address and chained
proxies.
|
protected void |
timedOut()
This method is called when the underlying
Channel times out due
to an idle timeout. |
(package private) void |
write(Object msg)
This method is called by users of the ProxyConnection to send stuff out
over the socket.
|
(package private) void |
write(Object msg,
HttpFilters filters)
Like
write(Object) and also sets the current filters to the
given value. |
protected void |
writeHttp(io.netty.handler.codec.http.HttpObject httpObject)
Writes HttpObjects to the connection asynchronously.
|
aggregateContentForFiltering, channelActive, channelInactive, channelRead0, channelRegistered, channelWritabilityChanged, connected, disconnect, doWrite, encrypt, encrypt, EncryptChannel, exceptionCaught, getCurrentState, getLOG, getSslEngine, is, isConnecting, isSaturated, isTunneling, resumeReading, stopReading, userEventTriggered, writeRaw, writeToChannel
acceptInboundMessage, channelRead
channelReadComplete, channelUnregistered
ensureNotSharable, handlerAdded, handlerRemoved, isSharable
private final ClientToProxyConnection clientConnection
private final ProxyToServerConnection serverConnection
private volatile TransportProtocol transportProtocol
private volatile InetSocketAddress remoteAddress
private volatile InetSocketAddress localAddress
private final String serverHostAndPort
private volatile ChainedProxy chainedProxy
private final Queue<ChainedProxy> availableChainedProxies
private volatile HttpFilters currentFilters
private volatile ConnectionFlow connectionFlow
private volatile boolean disableSni
initializeConnectionFlow()
. This value is set to true
when retrying a connection without SNI to work around Java's SNI handling issue (see
connectionFailed(Throwable)
).private final Object connectLock
private volatile io.netty.handler.codec.http.HttpRequest initialRequest
private final Queue<io.netty.handler.codec.http.HttpRequest> issuedRequests
private volatile io.netty.handler.codec.http.HttpRequest currentHttpRequest
private volatile io.netty.handler.codec.http.HttpResponse currentHttpResponse
private volatile io.netty.handler.traffic.GlobalTrafficShapingHandler trafficHandler
private static final int MINIMUM_RECV_BUFFER_SIZE_BYTES
private ConnectionFlowStep ConnectChannel
private ConnectionFlowStep HTTPCONNECTWithChainedProxy
private ConnectionFlowStep MitmEncryptClientChannel
Encrypts the client channel based on our server SSLSession
.
This does not wait for the handshake to finish so that we can go on and respond to the CONNECT request.
private final ProxyConnection.BytesReadMonitor bytesReadMonitor
private ProxyConnection.ResponseReadMonitor responseReadMonitor
private ProxyConnection.BytesWrittenMonitor bytesWrittenMonitor
private ProxyConnection.RequestWrittenMonitor requestWrittenMonitor
private ProxyToServerConnection(DefaultHttpProxyServer proxyServer, ClientToProxyConnection clientConnection, String serverHostAndPort, ChainedProxy chainedProxy, Queue<ChainedProxy> availableChainedProxies, HttpFilters initialFilters, io.netty.handler.traffic.GlobalTrafficShapingHandler globalTrafficShapingHandler) throws UnknownHostException
UnknownHostException
static ProxyToServerConnection create(DefaultHttpProxyServer proxyServer, ClientToProxyConnection clientConnection, String serverHostAndPort, HttpFilters initialFilters, io.netty.handler.codec.http.HttpRequest initialHttpRequest, io.netty.handler.traffic.GlobalTrafficShapingHandler globalTrafficShapingHandler) throws UnknownHostException
proxyServer
- clientConnection
- serverHostAndPort
- initialFilters
- initialHttpRequest
- UnknownHostException
protected void read(Object msg)
read
in class ProxyConnection<io.netty.handler.codec.http.HttpResponse>
protected ConnectionState readHTTPInitial(io.netty.handler.codec.http.HttpResponse httpResponse)
ProxyConnection
HttpRequest
or HttpResponse
).readHTTPInitial
in class ProxyConnection<io.netty.handler.codec.http.HttpResponse>
protected void readHTTPChunk(io.netty.handler.codec.http.HttpContent chunk)
ProxyConnection
readHTTPChunk
in class ProxyConnection<io.netty.handler.codec.http.HttpResponse>
protected void readRaw(io.netty.buffer.ByteBuf buf)
ProxyConnection
readRaw
in class ProxyConnection<io.netty.handler.codec.http.HttpResponse>
void write(Object msg, HttpFilters filters)
write(Object)
and also sets the current filters to the
given value.msg
- filters
- void write(Object msg)
ProxyConnection
write
in class ProxyConnection<io.netty.handler.codec.http.HttpResponse>
protected void writeHttp(io.netty.handler.codec.http.HttpObject httpObject)
ProxyConnection
writeHttp
in class ProxyConnection<io.netty.handler.codec.http.HttpResponse>
protected void become(ConnectionState newState)
become
in class ProxyConnection<io.netty.handler.codec.http.HttpResponse>
protected void becameSaturated()
ProxyConnection
becameSaturated
in class ProxyConnection<io.netty.handler.codec.http.HttpResponse>
protected void becameWritable()
ProxyConnection
becameWritable
in class ProxyConnection<io.netty.handler.codec.http.HttpResponse>
protected void timedOut()
ProxyConnection
Channel
times out due
to an idle timeout.timedOut
in class ProxyConnection<io.netty.handler.codec.http.HttpResponse>
protected void disconnected()
ProxyConnection
Channel
becomes
disconnected.disconnected
in class ProxyConnection<io.netty.handler.codec.http.HttpResponse>
protected void exceptionCaught(Throwable cause)
ProxyConnection
Channel
.exceptionCaught
in class ProxyConnection<io.netty.handler.codec.http.HttpResponse>
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)
ProxyConnection
getHttpFiltersFromProxyServer
in class ProxyConnection<io.netty.handler.codec.http.HttpResponse>
httpRequest
- Filter attached to the give HttpRequest (if any)private void identifyCurrentRequest()
private void rememberCurrentResponse(io.netty.handler.codec.http.HttpResponse response)
response
- private void respondWith(io.netty.handler.codec.http.HttpObject httpObject)
HttpObject
.httpObject
- private void connectAndWrite(io.netty.handler.codec.http.HttpRequest initialRequest)
ConnectionFlow
.initialRequest
- the current HTTP request being handledprivate void initializeConnectionFlow()
ConnectionFlow
based on however this connection has been configured. If
the disableSni
value is true, this method will not pass peer information to the MitmManager when
handling CONNECTs.protected boolean connectionFailed(Throwable cause) throws UnknownHostException
cause
- the reason that our attempt to connect failed (can be null)UnknownHostException
private void resetConnectionForRetry() throws UnknownHostException
setupConnectionParameters()
.UnknownHostException
- when setupConnectionParameters()
is unable to resolve the hostnameprivate void setupConnectionParameters() throws UnknownHostException
UnknownHostException
- when unable to resolve the hostname to an IP addressprivate void initChannelPipeline(io.netty.channel.ChannelPipeline pipeline, io.netty.handler.codec.http.HttpRequest httpRequest)
ChannelPipeline
.pipeline
- httpRequest
- void connectionSucceeded(boolean shouldForwardInitialRequest)
Do all the stuff that needs to be done after our ConnectionFlow
has succeeded.
shouldForwardInitialRequest
- whether or not we should forward the initial HttpRequest to
the server after the connection has been established.public static InetSocketAddress addressFor(String hostAndPort, DefaultHttpProxyServer proxyServer) throws UnknownHostException
InetSocketAddress
for the given hostAndPort.hostAndPort
- String representation of the host and portproxyServer
- the current DefaultHttpProxyServer
UnknownHostException
- if hostAndPort could not be resolved, or if the input string could not be parsed into
a host and port.Copyright © 2009–2018 LittleShoot. All rights reserved.