Class ProxyToServerConnection
- java.lang.Object
-
- io.netty.channel.ChannelHandlerAdapter
-
- io.netty.channel.ChannelInboundHandlerAdapter
-
- io.netty.channel.SimpleChannelInboundHandler<Object>
-
- org.littleshoot.proxy.impl.ProxyConnection<HttpResponse>
-
- org.littleshoot.proxy.impl.ProxyToServerConnection
-
- All Implemented Interfaces:
ChannelHandler,ChannelInboundHandler
@Sharable public class ProxyToServerConnection extends ProxyConnection<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
ProxyToServerConnectioncan involve more than just connecting the underlyingChannel. 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 propertyconnectionFlow, which is initialized ininitializeConnectionFlow().
-
-
Nested Class Summary
Nested Classes Modifier and Type Class Description private classProxyToServerConnection.HeadAwareHttpResponseDecoderResponses 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.-
Nested classes/interfaces inherited from class org.littleshoot.proxy.impl.ProxyConnection
ProxyConnection.BytesReadMonitor, ProxyConnection.BytesWrittenMonitor, ProxyConnection.RequestReadMonitor, ProxyConnection.RequestWrittenMonitor, ProxyConnection.ResponseReadMonitor, ProxyConnection.ResponseWrittenMonitor
-
Nested classes/interfaces inherited from interface io.netty.channel.ChannelHandler
ChannelHandler.Sharable
-
-
Field Summary
Fields Modifier and Type Field Description private Queue<ChainedProxy>availableChainedProxiesprivate ProxyConnection.BytesReadMonitorbytesReadMonitorprivate ProxyConnection.BytesWrittenMonitorbytesWrittenMonitorprivate ChainedProxychainedProxyprivate ChainedProxyTypechainedProxyTypeprivate ClientToProxyConnectionclientConnectionprivate ConnectionFlowStepConnectChannelOpens the socket connection.private ConnectionFlowconnectionFlowEncapsulates the flow for establishing a connection, which can vary depending on how things are configured.private ObjectconnectLockWhile we're in the process of connecting, it's possible that we'll receive a new message to write.private HttpFilterscurrentFiltersThe filters to apply to response/chunks received from server.private HttpRequestcurrentHttpRequestKeeps track of HttpRequests that have been issued so that we can associate them with responses that we get backprivate HttpResponsecurrentHttpResponseWhile we're doing a chunked transfer, this keeps track of the initial HttpResponse object for our transfer (which is useful for its headers).private booleandisableSniDisables SNI when initializing connection flow ininitializeConnectionFlow().private static StringHTTP_DECODER_NAMEprivate static StringHTTP_ENCODER_NAMEprivate static StringHTTP_PROXY_ENCODER_NAMEprivate static StringHTTP_REQUEST_WRITTEN_MONITOR_NAMEprivate static StringHTTP_RESPONSE_READ_MONITOR_NAMEprivate ConnectionFlowStepHTTPCONNECTWithChainedProxyWrites the HTTP CONNECT to the server and waits for a 200 response.private HttpRequestinitialRequestThis is the initial request received prior to connecting.private InetSocketAddresslocalAddressprivate static StringMAIN_HANDLER_NAMEprivate static intMINIMUM_RECV_BUFFER_SIZE_BYTESMinimum size of the adaptive recv buffer when throttling is enabled.private ConnectionFlowStepMitmEncryptClientChannelEncrypts the client channel based on our serverSSLSession.private Stringpasswordprivate InetSocketAddressremoteAddressprivate io.netty.resolver.AddressResolverGroup<?>remoteAddressResolverprivate ProxyConnection.RequestWrittenMonitorrequestWrittenMonitorprivate ProxyConnection.ResponseReadMonitorresponseReadMonitorprivate ProxyToServerConnectionserverConnectionprivate StringserverHostAndPortprivate static StringSOCKS_DECODER_NAMEprivate static StringSOCKS_ENCODER_NAMEprivate ConnectionFlowStepSOCKS4CONNECTWithChainedProxyEstablishes a SOCKS4 connection.private ConnectionFlowStepSOCKS5CONNECTRequestWithChainedProxyEstablishes a SOCKS5 connection afterSOCKS5InitialRequestand (optionally)SOCKS5SendPasswordCredentialshave completed.private ConnectionFlowStepSOCKS5InitialRequestInitiates a SOCKS5 connection.private ConnectionFlowStepSOCKS5SendPasswordCredentialsSends SOCKS5 password credentials afterSOCKS5InitialRequesthas completed.private GlobalTrafficShapingHandlertrafficHandlerLimits bandwidth when throttling is enabled.private TransportProtocoltransportProtocolprivate Stringusername-
Fields inherited from class org.littleshoot.proxy.impl.ProxyConnection
channel, ctx, lastReadTime, LOG, proxyServer, runsAsSslClient, sslEngine, StartTunneling
-
-
Constructor Summary
Constructors Modifier Constructor Description privateProxyToServerConnection(DefaultHttpProxyServer proxyServer, ClientToProxyConnection clientConnection, String serverHostAndPort, ChainedProxy chainedProxy, Queue<ChainedProxy> availableChainedProxies, HttpFilters initialFilters, GlobalTrafficShapingHandler globalTrafficShapingHandler)
-
Method Summary
All Methods Static Methods Instance Methods Concrete Methods Modifier and Type Method Description private voidaddFirstOrReplaceHandler(String name, ChannelHandler handler)static InetSocketAddressaddressFor(String hostAndPort, DefaultHttpProxyServer proxyServer)Build anInetSocketAddressfor the given hostAndPort.protected voidbecameSaturated()Callback that's invoked if this connection becomes saturated.protected voidbecameWritable()Callback that's invoked when this connection becomes writeable again.protected voidbecome(ConnectionState newState)Updates the current state to the given value.private voidconnectAndWrite(HttpRequest initialRequest)Configures the connection to the upstream server and begins theConnectionFlow.protected booleanconnectionFailed(Throwable cause)Called when the connection to the server or upstream chained proxy fails.(package private) voidconnectionSucceeded(boolean shouldForwardInitialRequest)Do all the stuff that needs to be done after ourConnectionFlowhas succeeded.(package private) static ProxyToServerConnectioncreate(DefaultHttpProxyServer proxyServer, ClientToProxyConnection clientConnection, String serverHostAndPort, HttpFilters initialFilters, HttpRequest initialHttpRequest, GlobalTrafficShapingHandler globalTrafficShapingHandler)Create a new ProxyToServerConnection.protected voiddisconnected()This method is called as soon as the underlyingChannelbecomes disconnected.protected voidexceptionCaught(Throwable cause)Override this to handle exceptions that occurred during asynchronous processing on theChannel.ChainedProxygetChainedProxy()InetSocketAddressgetChainedProxyAddress()ChainedProxyTypegetChainedProxyType()protected HttpFiltersgetHttpFiltersFromProxyServer(HttpRequest httpRequest)Request the ProxyServer for Filters.HttpRequestgetInitialRequest()InetSocketAddressgetRemoteAddress()StringgetServerHostAndPort()TransportProtocolgetTransportProtocol()booleanhasUpstreamChainedProxy()private voidinitChannelPipeline(ChannelPipeline pipeline, HttpRequest httpRequest)Initialize ourChannelPipelineto connect the upstream server.private voidinitializeConnectionFlow()This method initializes ourConnectionFlowbased on however this connection has been configured.protected voidread(Object msg)Read is invoked automatically by Netty as messages arrive on the socket.protected voidreadHAProxyMessage(HAProxyMessage msg)Read anHAProxyMessageprotected voidreadHTTPChunk(HttpContent chunk)Implement this to handle reading a chunk in a chunked transfer.protected ConnectionStatereadHTTPInitial(HttpResponse httpResponse)Implement this to handle reading the initial object (e.g.protected voidreadRaw(ByteBuf buf)Implement this to handle reading a raw buffer as they are used in HTTP tunneling.private voidrememberCurrentResponse(HttpResponse response)Keeps track of the current HttpResponse so that we can associate its headers with future related chunks for this same transfer.private voidremoveHandlerIfPresent(String name)private voidresetConnectionForRetry()Convenience method to prepare to retry this connection.private voidresetInitialRequest()private voidrespondWith(HttpObject httpObject)Respond to the client with the givenHttpObject.private voidsetupConnectionParameters()Set up our connection parameters based on server address and chained proxies.(package private) voidswitchToWebSocketProtocol()protected voidtimedOut()This method is called when the underlyingChanneltimes out due to an idle timeout.private static InetSocketAddressunresolvedAddressFor(String hostAndPort)Similar toaddressFor(String, DefaultHttpProxyServer)except that it does not resolve the address.(package private) voidwrite(Object msg)This method is called by users of the ProxyConnection to send stuff out over the socket.(package private) voidwrite(Object msg, HttpFilters filters)Likewrite(Object)and also sets the current filters to the given value.protected voidwriteHttp(HttpObject httpObject)Writes HttpObjects to the connection asynchronously.-
Methods inherited from class org.littleshoot.proxy.impl.ProxyConnection
aggregateContentForFiltering, channelActive, channelInactive, channelRead0, channelRegistered, channelUnregistered, channelWritabilityChanged, connected, disconnect, doWrite, encrypt, encrypt, EncryptChannel, exceptionCaught, getCurrentState, getLOG, getSslEngine, is, isConnecting, isSaturated, isTunneling, removeHandlerIfPresent, resumeReading, stopReading, userEventTriggered, writeRaw, writeToChannel
-
Methods inherited from class io.netty.channel.SimpleChannelInboundHandler
acceptInboundMessage, channelRead
-
Methods inherited from class io.netty.channel.ChannelInboundHandlerAdapter
channelReadComplete
-
Methods inherited from class io.netty.channel.ChannelHandlerAdapter
ensureNotSharable, 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
-
HTTP_ENCODER_NAME
private static final String HTTP_ENCODER_NAME
- See Also:
- Constant Field Values
-
HTTP_DECODER_NAME
private static final String HTTP_DECODER_NAME
- See Also:
- Constant Field Values
-
HTTP_PROXY_ENCODER_NAME
private static final String HTTP_PROXY_ENCODER_NAME
- See Also:
- Constant Field Values
-
HTTP_REQUEST_WRITTEN_MONITOR_NAME
private static final String HTTP_REQUEST_WRITTEN_MONITOR_NAME
- See Also:
- Constant Field Values
-
HTTP_RESPONSE_READ_MONITOR_NAME
private static final String HTTP_RESPONSE_READ_MONITOR_NAME
- See Also:
- Constant Field Values
-
SOCKS_ENCODER_NAME
private static final String SOCKS_ENCODER_NAME
- See Also:
- Constant Field Values
-
SOCKS_DECODER_NAME
private static final String SOCKS_DECODER_NAME
- See Also:
- Constant Field Values
-
MAIN_HANDLER_NAME
private static final String MAIN_HANDLER_NAME
- See Also:
- Constant Field Values
-
clientConnection
private final ClientToProxyConnection clientConnection
-
serverConnection
private final ProxyToServerConnection serverConnection
-
transportProtocol
private volatile TransportProtocol transportProtocol
-
chainedProxyType
private volatile ChainedProxyType chainedProxyType
-
remoteAddress
private volatile InetSocketAddress remoteAddress
-
localAddress
private volatile InetSocketAddress localAddress
-
remoteAddressResolver
private volatile io.netty.resolver.AddressResolverGroup<?> remoteAddressResolver
-
username
private volatile String username
-
password
private volatile String password
-
serverHostAndPort
private final String serverHostAndPort
-
chainedProxy
private volatile ChainedProxy chainedProxy
-
availableChainedProxies
private final Queue<ChainedProxy> availableChainedProxies
-
currentFilters
private volatile HttpFilters currentFilters
The filters to apply to response/chunks received from server.
-
connectionFlow
private volatile ConnectionFlow connectionFlow
Encapsulates the flow for establishing a connection, which can vary depending on how things are configured.
-
disableSni
private volatile boolean disableSni
Disables SNI when initializing connection flow ininitializeConnectionFlow(). This value is set to true when retrying a connection without SNI to work around Java's SNI handling issue (seeconnectionFailed(Throwable)).
-
connectLock
private final Object connectLock
While we're in the process of connecting, it's possible that we'll receive a new message to write. This lock helps us synchronize and wait for the connection to be established before writing the next message.
-
initialRequest
private volatile HttpRequest initialRequest
This is the initial request received prior to connecting. We keep track of it so that we can process it after connection finishes.
-
currentHttpRequest
private volatile HttpRequest currentHttpRequest
Keeps track of HttpRequests that have been issued so that we can associate them with responses that we get back
-
currentHttpResponse
private volatile 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).
-
trafficHandler
private final GlobalTrafficShapingHandler trafficHandler
Limits bandwidth when throttling is enabled.
-
MINIMUM_RECV_BUFFER_SIZE_BYTES
private static final int MINIMUM_RECV_BUFFER_SIZE_BYTES
Minimum size of the adaptive recv buffer when throttling is enabled.- See Also:
- Constant Field Values
-
ConnectChannel
private final ConnectionFlowStep ConnectChannel
Opens the socket connection.
-
HTTPCONNECTWithChainedProxy
private final ConnectionFlowStep HTTPCONNECTWithChainedProxy
Writes the HTTP CONNECT to the server and waits for a 200 response.
-
SOCKS4CONNECTWithChainedProxy
private final ConnectionFlowStep SOCKS4CONNECTWithChainedProxy
Establishes a SOCKS4 connection.
-
SOCKS5InitialRequest
private final ConnectionFlowStep SOCKS5InitialRequest
Initiates a SOCKS5 connection.
-
SOCKS5SendPasswordCredentials
private final ConnectionFlowStep SOCKS5SendPasswordCredentials
Sends SOCKS5 password credentials afterSOCKS5InitialRequesthas completed.
-
SOCKS5CONNECTRequestWithChainedProxy
private final ConnectionFlowStep SOCKS5CONNECTRequestWithChainedProxy
Establishes a SOCKS5 connection afterSOCKS5InitialRequestand (optionally)SOCKS5SendPasswordCredentialshave completed.
-
MitmEncryptClientChannel
private final 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.
-
bytesReadMonitor
private final ProxyConnection.BytesReadMonitor bytesReadMonitor
-
responseReadMonitor
private final ProxyConnection.ResponseReadMonitor responseReadMonitor
-
bytesWrittenMonitor
private final ProxyConnection.BytesWrittenMonitor bytesWrittenMonitor
-
requestWrittenMonitor
private final ProxyConnection.RequestWrittenMonitor requestWrittenMonitor
-
-
Constructor Detail
-
ProxyToServerConnection
private ProxyToServerConnection(DefaultHttpProxyServer proxyServer, ClientToProxyConnection clientConnection, String serverHostAndPort, ChainedProxy chainedProxy, Queue<ChainedProxy> availableChainedProxies, HttpFilters initialFilters, GlobalTrafficShapingHandler globalTrafficShapingHandler) throws UnknownHostException
- Throws:
UnknownHostException
-
-
Method Detail
-
create
static ProxyToServerConnection create(DefaultHttpProxyServer proxyServer, ClientToProxyConnection clientConnection, String serverHostAndPort, HttpFilters initialFilters, HttpRequest initialHttpRequest, GlobalTrafficShapingHandler globalTrafficShapingHandler) throws UnknownHostException
Create a new ProxyToServerConnection.- Throws:
UnknownHostException
-
read
protected void read(Object msg)
Description copied from class:ProxyConnectionRead is invoked automatically by Netty as messages arrive on the socket.- Overrides:
readin classProxyConnection<HttpResponse>
-
readHAProxyMessage
protected void readHAProxyMessage(HAProxyMessage msg)
Description copied from class:ProxyConnectionRead anHAProxyMessage- Specified by:
readHAProxyMessagein classProxyConnection<HttpResponse>- Parameters:
msg-HAProxyMessage
-
readHTTPInitial
protected ConnectionState readHTTPInitial(HttpResponse httpResponse)
Description copied from class:ProxyConnectionImplement this to handle reading the initial object (e.g.HttpRequestorHttpResponse).- Specified by:
readHTTPInitialin classProxyConnection<HttpResponse>
-
readHTTPChunk
protected void readHTTPChunk(HttpContent chunk)
Description copied from class:ProxyConnectionImplement this to handle reading a chunk in a chunked transfer.- Specified by:
readHTTPChunkin classProxyConnection<HttpResponse>
-
readRaw
protected void readRaw(ByteBuf buf)
Description copied from class:ProxyConnectionImplement this to handle reading a raw buffer as they are used in HTTP tunneling.- Specified by:
readRawin classProxyConnection<HttpResponse>
-
write
void write(Object msg, HttpFilters filters)
Likewrite(Object)and also sets the current filters to the given value.
-
write
void write(Object msg)
Description copied from class:ProxyConnectionThis method is called by users of the ProxyConnection to send stuff out over the socket.- Overrides:
writein classProxyConnection<HttpResponse>
-
writeHttp
protected void writeHttp(HttpObject httpObject)
Description copied from class:ProxyConnectionWrites HttpObjects to the connection asynchronously.- Overrides:
writeHttpin classProxyConnection<HttpResponse>
-
become
protected void become(ConnectionState newState)
Description copied from class:ProxyConnectionUpdates the current state to the given value.- Overrides:
becomein classProxyConnection<HttpResponse>
-
becameSaturated
protected void becameSaturated()
Description copied from class:ProxyConnectionCallback that's invoked if this connection becomes saturated.- Overrides:
becameSaturatedin classProxyConnection<HttpResponse>
-
becameWritable
protected void becameWritable()
Description copied from class:ProxyConnectionCallback that's invoked when this connection becomes writeable again.- Overrides:
becameWritablein classProxyConnection<HttpResponse>
-
timedOut
protected void timedOut()
Description copied from class:ProxyConnectionThis method is called when the underlyingChanneltimes out due to an idle timeout.- Overrides:
timedOutin classProxyConnection<HttpResponse>
-
disconnected
protected void disconnected()
Description copied from class:ProxyConnectionThis method is called as soon as the underlyingChannelbecomes disconnected.- Overrides:
disconnectedin classProxyConnection<HttpResponse>
-
exceptionCaught
protected void exceptionCaught(Throwable cause)
Description copied from class:ProxyConnectionOverride this to handle exceptions that occurred during asynchronous processing on theChannel.- Overrides:
exceptionCaughtin classProxyConnection<HttpResponse>
-
getTransportProtocol
public TransportProtocol getTransportProtocol()
-
getChainedProxyType
public ChainedProxyType getChainedProxyType()
-
getRemoteAddress
public InetSocketAddress getRemoteAddress()
-
getServerHostAndPort
public String getServerHostAndPort()
-
hasUpstreamChainedProxy
public boolean hasUpstreamChainedProxy()
-
getChainedProxyAddress
public InetSocketAddress getChainedProxyAddress()
-
getChainedProxy
public ChainedProxy getChainedProxy()
-
getInitialRequest
public HttpRequest getInitialRequest()
-
getHttpFiltersFromProxyServer
protected HttpFilters getHttpFiltersFromProxyServer(HttpRequest httpRequest)
Description copied from class:ProxyConnectionRequest the ProxyServer for Filters. By default, no-op filters are returned by DefaultHttpProxyServer. Subclasses of ProxyConnection can change this behaviour.- Overrides:
getHttpFiltersFromProxyServerin classProxyConnection<HttpResponse>- Parameters:
httpRequest- Filter attached to the give HttpRequest (if any)
-
rememberCurrentResponse
private void rememberCurrentResponse(HttpResponse response)
Keeps track of the current HttpResponse so that we can associate its headers with future related chunks for this same transfer.
-
respondWith
private void respondWith(HttpObject httpObject)
Respond to the client with the givenHttpObject.
-
connectAndWrite
private void connectAndWrite(HttpRequest initialRequest)
Configures the connection to the upstream server and begins theConnectionFlow.- Parameters:
initialRequest- the current HTTP request being handled
-
initializeConnectionFlow
private void initializeConnectionFlow()
This method initializes ourConnectionFlowbased on however this connection has been configured. If thedisableSnivalue is true, this method will not pass peer information to the MitmManager when handling CONNECTs.
-
addFirstOrReplaceHandler
private void addFirstOrReplaceHandler(String name, ChannelHandler handler)
-
removeHandlerIfPresent
private void removeHandlerIfPresent(String name)
-
connectionFailed
protected boolean connectionFailed(Throwable cause) throws UnknownHostException
Called when the connection to the server or upstream chained proxy fails. This method may return true to indicate that the connection should be retried. If returning true, this method must set up the connection itself.- 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
-
resetConnectionForRetry
private void resetConnectionForRetry() throws UnknownHostExceptionConvenience method to prepare to retry this connection. Closes the connection's channel and sets up the connection again usingsetupConnectionParameters().- Throws:
UnknownHostException- whensetupConnectionParameters()is unable to resolve the hostname
-
setupConnectionParameters
private void setupConnectionParameters() throws UnknownHostExceptionSet up our connection parameters based on server address and chained proxies.- Throws:
UnknownHostException- when unable to resolve the hostname to an IP address
-
initChannelPipeline
private void initChannelPipeline(ChannelPipeline pipeline, HttpRequest httpRequest)
Initialize ourChannelPipelineto connect the upstream server. LittleProxy acts as a client here. AChannelPipelineinvokes the read (Inbound) handlers in ascending ordering of the list and then the write (Outbound) handlers in descending ordering. Regarding the Javadoc ofHttpObjectAggregatorit's needed to have theHttpResponseEncoderorHttpRequestEncoderbefore theHttpObjectAggregatorin theChannelPipeline.
-
connectionSucceeded
void connectionSucceeded(boolean shouldForwardInitialRequest)
Do all the stuff that needs to be done after our
ConnectionFlowhas succeeded.- Parameters:
shouldForwardInitialRequest- whether or not we should forward the initial HttpRequest to the server after the connection has been established.
-
resetInitialRequest
private void resetInitialRequest()
-
addressFor
public static InetSocketAddress addressFor(String hostAndPort, DefaultHttpProxyServer proxyServer) throws UnknownHostException
Build anInetSocketAddressfor the given hostAndPort.- Parameters:
hostAndPort- String representation of the host and portproxyServer- the currentDefaultHttpProxyServer- Returns:
- a resolved InetSocketAddress for the specified hostAndPort
- Throws:
UnknownHostException- if hostAndPort could not be resolved, or if the input string could not be parsed into a host and port.
-
unresolvedAddressFor
private static InetSocketAddress unresolvedAddressFor(String hostAndPort)
Similar toaddressFor(String, DefaultHttpProxyServer)except that it does not resolve the address.- Parameters:
hostAndPort- the host and port to parse.- Returns:
- an unresolved
InetSocketAddress.
-
switchToWebSocketProtocol
void switchToWebSocketProtocol()
-
-