From b8e68326ed2cc704eae9faab234408a47e88bac7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stefan=20Sch=C3=B6ffmann?= Date: Sun, 11 Jan 2015 13:06:36 +0100 Subject: [PATCH 1/2] Extended the API so you can also determine the network interface to be used by the proxy for outgoing traffic (neat in case you have more than one IP address) --- .../proxy/HttpProxyServerBootstrap.java | 10 +- .../java/org/littleshoot/proxy/Launcher.java | 24 ++- .../proxy/impl/DefaultHttpProxyServer.java | 29 +++- .../proxy/impl/ProxyToServerConnection.java | 141 ++++++++++-------- 4 files changed, 126 insertions(+), 78 deletions(-) diff --git a/src/main/java/org/littleshoot/proxy/HttpProxyServerBootstrap.java b/src/main/java/org/littleshoot/proxy/HttpProxyServerBootstrap.java index 7e512fe37..82aeb480a 100644 --- a/src/main/java/org/littleshoot/proxy/HttpProxyServerBootstrap.java +++ b/src/main/java/org/littleshoot/proxy/HttpProxyServerBootstrap.java @@ -293,13 +293,19 @@ HttpProxyServerBootstrap withConnectTimeout( */ HttpProxyServerBootstrap withThrottling(long readThrottleBytesPerSecond, long writeThrottleBytesPerSecond); + /** + * All outgoing-communication of the proxy-instance is goin' to be routed via the given network-interface + * + * @param inetSocketAddress to be used for outgoing communication + */ + HttpProxyServerBootstrap useNetworkInterface(InetSocketAddress inetSocketAddress); + /** *

* Build and starts the server. *

- * + * * @return the newly built and started server */ HttpProxyServer start(); - } \ No newline at end of file diff --git a/src/main/java/org/littleshoot/proxy/Launcher.java b/src/main/java/org/littleshoot/proxy/Launcher.java index 825f77007..cc96ee121 100755 --- a/src/main/java/org/littleshoot/proxy/Launcher.java +++ b/src/main/java/org/littleshoot/proxy/Launcher.java @@ -1,8 +1,5 @@ package org.littleshoot.proxy; -import java.io.File; -import java.util.Arrays; - import org.apache.commons.cli.CommandLine; import org.apache.commons.cli.CommandLineParser; import org.apache.commons.cli.HelpFormatter; @@ -11,7 +8,6 @@ import org.apache.commons.cli.PosixParser; import org.apache.commons.cli.UnrecognizedOptionException; import org.apache.commons.lang3.StringUtils; -import org.apache.log4j.PropertyConfigurator; import org.apache.log4j.xml.DOMConfigurator; import org.littleshoot.proxy.extras.SelfSignedMitmManager; import org.littleshoot.proxy.impl.DefaultHttpProxyServer; @@ -19,6 +15,10 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import java.io.File; +import java.net.InetSocketAddress; +import java.util.Arrays; + /** * Launches a new HTTP proxy. */ @@ -31,9 +31,11 @@ public class Launcher { private static final String OPTION_PORT = "port"; private static final String OPTION_HELP = "help"; - + private static final String OPTION_MITM = "mitm"; + private static final String OPTION_NIC = "nic"; + /** * Starts the proxy from the command line. * @@ -47,6 +49,7 @@ public static void main(final String... args) { options.addOption(null, OPTION_DNSSEC, true, "Request and verify DNSSEC signatures."); options.addOption(null, OPTION_PORT, true, "Run on the specified port."); + options.addOption(null, OPTION_NIC, true, "Run on a specified Nic"); options.addOption(null, OPTION_HELP, false, "Display command line help."); options.addOption(null, OPTION_MITM, false, "Run as man in the middle."); @@ -83,12 +86,18 @@ public static void main(final String... args) { port = defaultPort; } + System.out.println("About to start server on port: " + port); HttpProxyServerBootstrap bootstrap = DefaultHttpProxyServer .bootstrapFromFile("./littleproxy.properties") .withPort(port) .withAllowLocalOnly(false); - + + if (cmd.hasOption(OPTION_NIC)) { + final String val = cmd.getOptionValue(OPTION_NIC); + bootstrap.useNetworkInterface(new InetSocketAddress(val, 0)); + } + if (cmd.hasOption(OPTION_MITM)) { LOG.info("Running as Man in the Middle"); bootstrap.withManInTheMiddle(new SelfSignedMitmManager()); @@ -125,8 +134,7 @@ private static void printHelp(final Options options, } private static void pollLog4JConfigurationFileIfAvailable() { - File log4jConfigurationFile = new File( - "src/test/resources/log4j.xml"); + File log4jConfigurationFile = new File("src/test/resources/log4j.xml"); if (log4jConfigurationFile.exists()) { DOMConfigurator.configureAndWatch( log4jConfigurationFile.getAbsolutePath(), 15); diff --git a/src/main/java/org/littleshoot/proxy/impl/DefaultHttpProxyServer.java b/src/main/java/org/littleshoot/proxy/impl/DefaultHttpProxyServer.java index 2636d95af..52429ef6c 100644 --- a/src/main/java/org/littleshoot/proxy/impl/DefaultHttpProxyServer.java +++ b/src/main/java/org/littleshoot/proxy/impl/DefaultHttpProxyServer.java @@ -1,6 +1,8 @@ package org.littleshoot.proxy.impl; import static org.littleshoot.proxy.TransportProtocol.*; + +import com.google.common.base.Optional; import io.netty.bootstrap.ChannelFactory; import io.netty.bootstrap.ServerBootstrap; import io.netty.channel.Channel; @@ -105,6 +107,7 @@ public class DefaultHttpProxyServer implements HttpProxyServer { * The actual address to which the server is bound. May be different from the requestedAddress in some circumstances, * for example when the requested port is 0. */ + private volatile InetSocketAddress localAddress; private volatile InetSocketAddress boundAddress; private final SslEngineSource sslEngineSource; private final boolean authenticateSslClients; @@ -217,7 +220,8 @@ private DefaultHttpProxyServer(ServerGroup serverGroup, int connectTimeout, HostResolver serverResolver, long readThrottleBytesPerSecond, - long writeThrottleBytesPerSecond) { + long writeThrottleBytesPerSecond, + InetSocketAddress localAddress) { this.serverGroup = serverGroup; this.transportProtocol = transportProtocol; this.requestedAddress = requestedAddress; @@ -240,6 +244,7 @@ private DefaultHttpProxyServer(ServerGroup serverGroup, } else { this.globalTrafficShapingHandler = null; } + this.localAddress = localAddress; } /** @@ -280,6 +285,10 @@ public HostResolver getServerResolver() { return serverResolver; } + public InetSocketAddress getLocalAddress() { + return localAddress; + } + @Override public InetSocketAddress getListenAddress() { return boundAddress; @@ -322,7 +331,8 @@ public HttpProxyServerBootstrap clone() { connectTimeout, serverResolver, globalTrafficShapingHandler != null ? globalTrafficShapingHandler.getReadLimit() : 0, - globalTrafficShapingHandler != null ? globalTrafficShapingHandler.getWriteLimit() : 0); + globalTrafficShapingHandler != null ? globalTrafficShapingHandler.getWriteLimit() : 0, + localAddress); } @Override @@ -632,6 +642,7 @@ private static class DefaultHttpProxyServerBootstrap implements private HostResolver serverResolver = new DefaultHostResolver(); private long readThrottleBytesPerSecond; private long writeThrottleBytesPerSecond; + private InetSocketAddress localAddress; private DefaultHttpProxyServerBootstrap() { } @@ -649,7 +660,9 @@ private DefaultHttpProxyServerBootstrap( boolean transparent, int idleConnectionTimeout, Collection activityTrackers, int connectTimeout, HostResolver serverResolver, - long readThrottleBytesPerSecond, long writeThrottleBytesPerSecond) { + long readThrottleBytesPerSecond, + long writeThrottleBytesPerSecond, + InetSocketAddress localAddress) { this.original = original; this.transportProtocol = transportProtocol; this.requestedAddress = requestedAddress; @@ -668,6 +681,7 @@ private DefaultHttpProxyServerBootstrap( this.serverResolver = serverResolver; this.readThrottleBytesPerSecond = readThrottleBytesPerSecond; this.writeThrottleBytesPerSecond = writeThrottleBytesPerSecond; + this.localAddress = localAddress; } private DefaultHttpProxyServerBootstrap(Properties props) { @@ -707,6 +721,12 @@ public HttpProxyServerBootstrap withPort(int port) { return this; } + @Override + public HttpProxyServerBootstrap useNetworkInterface(InetSocketAddress inetSocketAddress) { + this.localAddress = inetSocketAddress; + return this; + } + @Override public HttpProxyServerBootstrap withAllowLocalOnly( boolean allowLocalOnly) { @@ -844,7 +864,8 @@ transportProtocol, determineListenAddress(), proxyAuthenticator, chainProxyManager, mitmManager, filtersSource, transparent, idleConnectionTimeout, activityTrackers, connectTimeout, - serverResolver, readThrottleBytesPerSecond, writeThrottleBytesPerSecond); + serverResolver, readThrottleBytesPerSecond, writeThrottleBytesPerSecond, + localAddress); } private InetSocketAddress determineListenAddress() { diff --git a/src/main/java/org/littleshoot/proxy/impl/ProxyToServerConnection.java b/src/main/java/org/littleshoot/proxy/impl/ProxyToServerConnection.java index cf2ac129f..60538d4ec 100644 --- a/src/main/java/org/littleshoot/proxy/impl/ProxyToServerConnection.java +++ b/src/main/java/org/littleshoot/proxy/impl/ProxyToServerConnection.java @@ -3,7 +3,6 @@ import io.netty.bootstrap.Bootstrap; import io.netty.bootstrap.ChannelFactory; import io.netty.buffer.ByteBuf; -import io.netty.channel.AdaptiveRecvByteBufAllocator; import io.netty.channel.Channel; import io.netty.channel.ChannelHandler.Sharable; import io.netty.channel.ChannelInitializer; @@ -39,7 +38,10 @@ import javax.net.ssl.SSLSession; import java.net.ConnectException; import java.net.InetSocketAddress; +import java.net.NetworkInterface; +import java.net.SocketException; import java.net.UnknownHostException; +import java.util.Enumeration; import java.util.LinkedList; import java.util.Queue; import java.util.concurrent.ConcurrentLinkedQueue; @@ -57,7 +59,7 @@ * ProxyConnections are reused fairly liberally, and can go from disconnected to * connected, back to disconnected and so on. *

- * + *

*

* Connecting a {@link ProxyToServerConnection} can involve more than just * connecting the underlying {@link Channel}. In particular, the connection may @@ -126,13 +128,13 @@ public class ProxyToServerConnection extends ProxyConnection { private volatile GlobalTrafficShapingHandler trafficHandler; /** - * Minimum size of the adaptive recv buffer when throttling is enabled. + * Minimum size of the adaptive recv buffer when throttling is enabled. */ private static final int MINIMUM_RECV_BUFFER_SIZE_BYTES = 64; - + /** * Create a new ProxyToServerConnection. - * + * * @param proxyServer * @param clientConnection * @param serverHostAndPort @@ -142,11 +144,11 @@ public class ProxyToServerConnection extends ProxyConnection { * @throws UnknownHostException */ static ProxyToServerConnection create(DefaultHttpProxyServer proxyServer, - ClientToProxyConnection clientConnection, - String serverHostAndPort, - HttpFilters initialFilters, - HttpRequest initialHttpRequest, - GlobalTrafficShapingHandler globalTrafficShapingHandler) + ClientToProxyConnection clientConnection, + String serverHostAndPort, + HttpFilters initialFilters, + HttpRequest initialHttpRequest, + GlobalTrafficShapingHandler globalTrafficShapingHandler) throws UnknownHostException { Queue chainedProxies = new ConcurrentLinkedQueue(); ChainedProxyManager chainedProxyManager = proxyServer @@ -191,9 +193,11 @@ private ProxyToServerConnection( setupConnectionParameters(); } - /*************************************************************************** + /** + * ************************************************************************ * Reading - **************************************************************************/ + * ************************************************************************ + */ @Override protected void read(Object msg) { @@ -240,12 +244,12 @@ protected void readRaw(ByteBuf buf) { * 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. *

- * + *

*

* See the documentation for {@link HttpResponseDecoder} for information * about why HEAD requests need special handling. *

- * + *

*

* Thanks to nataliakoval for * pointing out that with connections being reused as they are, this needs @@ -255,7 +259,7 @@ protected void readRaw(ByteBuf buf) { private class HeadAwareHttpResponseDecoder extends HttpResponseDecoder { public HeadAwareHttpResponseDecoder(int maxInitialLineLength, - int maxHeaderSize, int maxChunkSize) { + int maxHeaderSize, int maxChunkSize) { super(maxInitialLineLength, maxHeaderSize, maxChunkSize); } @@ -269,7 +273,9 @@ protected boolean isContentAlwaysEmpty(HttpMessage httpMessage) { return HttpMethod.HEAD.equals(currentHttpRequest.getMethod()) ? true : super.isContentAlwaysEmpty(httpMessage); } - }; + } + + ; /*************************************************************************** * Writing @@ -278,7 +284,7 @@ protected boolean isContentAlwaysEmpty(HttpMessage httpMessage) { /** * Like {@link #write(Object)} and also sets the current filters to the * given value. - * + * * @param msg * @param filters */ @@ -319,7 +325,9 @@ void write(Object msg) { LOG.debug("Using existing connection to: {}", remoteAddress); doWrite(msg); } - }; + } + + ; @Override protected void writeHttp(HttpObject httpObject) { @@ -334,9 +342,11 @@ protected void writeHttp(HttpObject httpObject) { super.writeHttp(httpObject); } - /*************************************************************************** + /** + * ************************************************************************ * Lifecycle - **************************************************************************/ + * ************************************************************************ + */ @Override protected void become(ConnectionState newState) { @@ -422,9 +432,11 @@ protected void exceptionCaught(Throwable cause) { // connection, so there should not be any further action to take here. } - /*************************************************************************** + /** + * ************************************************************************ * State Management - **************************************************************************/ + * ************************************************************************ + */ public TransportProtocol getTransportProtocol() { return transportProtocol; } @@ -486,7 +498,7 @@ private void identifyCurrentRequest() { /** * Keeps track of the current HttpResponse so that we can associate its * headers with future related chunks for this same transfer. - * + * * @param response */ private void rememberCurrentResponse(HttpResponse response) { @@ -501,7 +513,7 @@ private void rememberCurrentResponse(HttpResponse response) { /** * Respond to the client with the given {@link HttpObject}. - * + * * @param httpObject */ private void respondWith(HttpObject httpObject) { @@ -512,7 +524,7 @@ private void respondWith(HttpObject httpObject) { /** * Connects to the server and then writes out the initial request (or * upgrades to an SSL tunnel, depending). - * + * * @param initialRequest */ private void connectAndWrite(final HttpRequest initialRequest) { @@ -577,33 +589,36 @@ protected Future execute() { .getProxyToServerWorkerFor(transportProtocol)); switch (transportProtocol) { - case TCP: - LOG.debug("Connecting to server with TCP"); - cb.channelFactory(new ChannelFactory() { - @Override - public Channel newChannel() { - return new NioSocketChannel(); - } - }); - break; - case UDT: - LOG.debug("Connecting to server with UDT"); - cb.channelFactory(NioUdtProvider.BYTE_CONNECTOR) - .option(ChannelOption.SO_REUSEADDR, true); - break; - default: - throw new UnknownTransportProtocolError(transportProtocol); + case TCP: + LOG.debug("Connecting to server with TCP"); + cb.channelFactory(new ChannelFactory() { + @Override + public Channel newChannel() { + return new NioSocketChannel(); + } + }); + break; + case UDT: + LOG.debug("Connecting to server with UDT"); + cb.channelFactory(NioUdtProvider.BYTE_CONNECTOR) + .option(ChannelOption.SO_REUSEADDR, true); + break; + default: + throw new UnknownTransportProtocolError(transportProtocol); } cb.handler(new ChannelInitializer() { protected void initChannel(Channel ch) throws Exception { initChannelPipeline(ch.pipeline(), initialRequest); - }; + } + + ; }); cb.option(ChannelOption.CONNECT_TIMEOUT_MILLIS, proxyServer.getConnectTimeout()); if (localAddress != null) { + cb.bind(localAddress); return cb.connect(remoteAddress, localAddress); } else { return cb.connect(remoteAddress); @@ -650,7 +665,7 @@ void read(ConnectionFlow flow, Object msg) { *

* Encrypts the client channel based on our server {@link SSLSession}. *

- * + *

*

* This does not wait for the handshake to finish so that we can go on and * respond to the CONNECT request. @@ -691,14 +706,13 @@ public void operationComplete( *

* Called to let us know that connection failed. *

- * + *

*

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

- * - * @param cause - * the reason that our attempt to connect failed (can be null) + * + * @param cause the reason that our attempt to connect failed (can be null) * @return true if we are trying to fall back to another connection */ protected boolean connectionFailed(Throwable cause) @@ -728,7 +742,7 @@ protected boolean connectionFailed(Throwable cause) /** * Set up our connection parameters based on server address and chained * proxies. - * + * * @throws UnknownHostException */ private void setupConnectionParameters() throws UnknownHostException { @@ -753,18 +767,18 @@ private void setupConnectionParameters() throws UnknownHostException { this.currentFilters.proxyToServerResolutionSucceeded( serverHostAndPort, this.remoteAddress); - this.localAddress = null; + this.localAddress = proxyServer.getLocalAddress(); } } /** * Initialize our {@link ChannelPipeline}. - * + * * @param pipeline * @param httpRequest */ private void initChannelPipeline(ChannelPipeline pipeline, - HttpRequest httpRequest) { + HttpRequest httpRequest) { if (trafficHandler != null) { pipeline.addLast("global-traffic-shaping", trafficHandler); @@ -804,10 +818,9 @@ private void initChannelPipeline(ChannelPipeline pipeline, * Do all the stuff that needs to be done after our {@link ConnectionFlow} * has succeeded. *

- * - * @param shouldForwardInitialRequest - * whether or not we should forward the initial HttpRequest to - * the server after the connection has been established. + * + * @param shouldForwardInitialRequest whether or not we should forward the initial HttpRequest to + * the server after the connection has been established. */ void connectionSucceeded(boolean shouldForwardInitialRequest) { become(AWAITING_INITIAL); @@ -832,16 +845,14 @@ void connectionSucceeded(boolean shouldForwardInitialRequest) { /** * Build an {@link InetSocketAddress} for the given hostAndPort. - * + * * @param hostAndPort - * @param proxyServer - * the current {@link DefaultHttpProxyServer} + * @param proxyServer the current {@link DefaultHttpProxyServer} * @return - * @throws UnknownHostException - * if hostAndPort could not be resolved + * @throws UnknownHostException if hostAndPort could not be resolved */ private static InetSocketAddress addressFor(String hostAndPort, - DefaultHttpProxyServer proxyServer) + DefaultHttpProxyServer proxyServer) throws UnknownHostException { String host; int port; @@ -858,12 +869,14 @@ private static InetSocketAddress addressFor(String hostAndPort, return proxyServer.getServerResolver().resolve(host, port); } - /*************************************************************************** + /** + * ************************************************************************ * Activity Tracking/Statistics - * + *

* We track statistics on bytes, requests and responses by adding handlers * at the appropriate parts of the pipeline (see initChannelPipeline()). - **************************************************************************/ + * ************************************************************************ + */ private final BytesReadMonitor bytesReadMonitor = new BytesReadMonitor() { @Override protected void bytesRead(int numberOfBytes) { From 7f0800852fa57e094c46c955903cc629520e201f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stefan=20Sch=C3=B6ffmann?= Date: Tue, 3 Mar 2015 20:43:00 +0100 Subject: [PATCH 2/2] rework based on review-notes Reintroduced trailing spaces where my IDE was too eager in removing 'em and adjusted the name of the new interface-method to 'withNetworkInterface' --- .../proxy/HttpProxyServerBootstrap.java | 3 +- .../java/org/littleshoot/proxy/Launcher.java | 2 +- .../proxy/impl/DefaultHttpProxyServer.java | 4 +- .../proxy/impl/ProxyToServerConnection.java | 137 ++++++++---------- 4 files changed, 66 insertions(+), 80 deletions(-) diff --git a/src/main/java/org/littleshoot/proxy/HttpProxyServerBootstrap.java b/src/main/java/org/littleshoot/proxy/HttpProxyServerBootstrap.java index 82aeb480a..c4241e7ad 100644 --- a/src/main/java/org/littleshoot/proxy/HttpProxyServerBootstrap.java +++ b/src/main/java/org/littleshoot/proxy/HttpProxyServerBootstrap.java @@ -298,7 +298,7 @@ HttpProxyServerBootstrap withConnectTimeout( * * @param inetSocketAddress to be used for outgoing communication */ - HttpProxyServerBootstrap useNetworkInterface(InetSocketAddress inetSocketAddress); + HttpProxyServerBootstrap withNetworkInterface(InetSocketAddress inetSocketAddress); /** *

@@ -308,4 +308,5 @@ HttpProxyServerBootstrap withConnectTimeout( * @return the newly built and started server */ HttpProxyServer start(); + } \ No newline at end of file diff --git a/src/main/java/org/littleshoot/proxy/Launcher.java b/src/main/java/org/littleshoot/proxy/Launcher.java index cc96ee121..f9b654a0e 100755 --- a/src/main/java/org/littleshoot/proxy/Launcher.java +++ b/src/main/java/org/littleshoot/proxy/Launcher.java @@ -95,7 +95,7 @@ public static void main(final String... args) { if (cmd.hasOption(OPTION_NIC)) { final String val = cmd.getOptionValue(OPTION_NIC); - bootstrap.useNetworkInterface(new InetSocketAddress(val, 0)); + bootstrap.withNetworkInterface(new InetSocketAddress(val, 0)); } if (cmd.hasOption(OPTION_MITM)) { diff --git a/src/main/java/org/littleshoot/proxy/impl/DefaultHttpProxyServer.java b/src/main/java/org/littleshoot/proxy/impl/DefaultHttpProxyServer.java index 52429ef6c..9127bc37d 100644 --- a/src/main/java/org/littleshoot/proxy/impl/DefaultHttpProxyServer.java +++ b/src/main/java/org/littleshoot/proxy/impl/DefaultHttpProxyServer.java @@ -1,8 +1,6 @@ package org.littleshoot.proxy.impl; import static org.littleshoot.proxy.TransportProtocol.*; - -import com.google.common.base.Optional; import io.netty.bootstrap.ChannelFactory; import io.netty.bootstrap.ServerBootstrap; import io.netty.channel.Channel; @@ -722,7 +720,7 @@ public HttpProxyServerBootstrap withPort(int port) { } @Override - public HttpProxyServerBootstrap useNetworkInterface(InetSocketAddress inetSocketAddress) { + public HttpProxyServerBootstrap withNetworkInterface(InetSocketAddress inetSocketAddress) { this.localAddress = inetSocketAddress; return this; } diff --git a/src/main/java/org/littleshoot/proxy/impl/ProxyToServerConnection.java b/src/main/java/org/littleshoot/proxy/impl/ProxyToServerConnection.java index 60538d4ec..bbc2c5196 100644 --- a/src/main/java/org/littleshoot/proxy/impl/ProxyToServerConnection.java +++ b/src/main/java/org/littleshoot/proxy/impl/ProxyToServerConnection.java @@ -38,10 +38,7 @@ import javax.net.ssl.SSLSession; import java.net.ConnectException; import java.net.InetSocketAddress; -import java.net.NetworkInterface; -import java.net.SocketException; import java.net.UnknownHostException; -import java.util.Enumeration; import java.util.LinkedList; import java.util.Queue; import java.util.concurrent.ConcurrentLinkedQueue; @@ -59,7 +56,7 @@ * ProxyConnections are reused fairly liberally, and can go from disconnected to * connected, back to disconnected and so on. *

- *

+ * *

* Connecting a {@link ProxyToServerConnection} can involve more than just * connecting the underlying {@link Channel}. In particular, the connection may @@ -128,13 +125,13 @@ public class ProxyToServerConnection extends ProxyConnection { private volatile GlobalTrafficShapingHandler trafficHandler; /** - * Minimum size of the adaptive recv buffer when throttling is enabled. + * Minimum size of the adaptive recv buffer when throttling is enabled. */ private static final int MINIMUM_RECV_BUFFER_SIZE_BYTES = 64; - + /** * Create a new ProxyToServerConnection. - * + * * @param proxyServer * @param clientConnection * @param serverHostAndPort @@ -144,11 +141,11 @@ public class ProxyToServerConnection extends ProxyConnection { * @throws UnknownHostException */ static ProxyToServerConnection create(DefaultHttpProxyServer proxyServer, - ClientToProxyConnection clientConnection, - String serverHostAndPort, - HttpFilters initialFilters, - HttpRequest initialHttpRequest, - GlobalTrafficShapingHandler globalTrafficShapingHandler) + ClientToProxyConnection clientConnection, + String serverHostAndPort, + HttpFilters initialFilters, + HttpRequest initialHttpRequest, + GlobalTrafficShapingHandler globalTrafficShapingHandler) throws UnknownHostException { Queue chainedProxies = new ConcurrentLinkedQueue(); ChainedProxyManager chainedProxyManager = proxyServer @@ -193,11 +190,9 @@ private ProxyToServerConnection( setupConnectionParameters(); } - /** - * ************************************************************************ + /*************************************************************************** * Reading - * ************************************************************************ - */ + **************************************************************************/ @Override protected void read(Object msg) { @@ -244,12 +239,12 @@ protected void readRaw(ByteBuf buf) { * 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. *

- *

+ * *

* See the documentation for {@link HttpResponseDecoder} for information * about why HEAD requests need special handling. *

- *

+ * *

* Thanks to nataliakoval for * pointing out that with connections being reused as they are, this needs @@ -259,7 +254,7 @@ protected void readRaw(ByteBuf buf) { private class HeadAwareHttpResponseDecoder extends HttpResponseDecoder { public HeadAwareHttpResponseDecoder(int maxInitialLineLength, - int maxHeaderSize, int maxChunkSize) { + int maxHeaderSize, int maxChunkSize) { super(maxInitialLineLength, maxHeaderSize, maxChunkSize); } @@ -273,9 +268,7 @@ protected boolean isContentAlwaysEmpty(HttpMessage httpMessage) { return HttpMethod.HEAD.equals(currentHttpRequest.getMethod()) ? true : super.isContentAlwaysEmpty(httpMessage); } - } - - ; + }; /*************************************************************************** * Writing @@ -284,7 +277,7 @@ protected boolean isContentAlwaysEmpty(HttpMessage httpMessage) { /** * Like {@link #write(Object)} and also sets the current filters to the * given value. - * + * * @param msg * @param filters */ @@ -325,9 +318,7 @@ void write(Object msg) { LOG.debug("Using existing connection to: {}", remoteAddress); doWrite(msg); } - } - - ; + }; @Override protected void writeHttp(HttpObject httpObject) { @@ -342,11 +333,9 @@ protected void writeHttp(HttpObject httpObject) { super.writeHttp(httpObject); } - /** - * ************************************************************************ + /*************************************************************************** * Lifecycle - * ************************************************************************ - */ + **************************************************************************/ @Override protected void become(ConnectionState newState) { @@ -432,11 +421,9 @@ protected void exceptionCaught(Throwable cause) { // connection, so there should not be any further action to take here. } - /** - * ************************************************************************ + /*************************************************************************** * State Management - * ************************************************************************ - */ + **************************************************************************/ public TransportProtocol getTransportProtocol() { return transportProtocol; } @@ -498,7 +485,7 @@ private void identifyCurrentRequest() { /** * Keeps track of the current HttpResponse so that we can associate its * headers with future related chunks for this same transfer. - * + * * @param response */ private void rememberCurrentResponse(HttpResponse response) { @@ -513,7 +500,7 @@ private void rememberCurrentResponse(HttpResponse response) { /** * Respond to the client with the given {@link HttpObject}. - * + * * @param httpObject */ private void respondWith(HttpObject httpObject) { @@ -524,7 +511,7 @@ private void respondWith(HttpObject httpObject) { /** * Connects to the server and then writes out the initial request (or * upgrades to an SSL tunnel, depending). - * + * * @param initialRequest */ private void connectAndWrite(final HttpRequest initialRequest) { @@ -589,30 +576,28 @@ protected Future execute() { .getProxyToServerWorkerFor(transportProtocol)); switch (transportProtocol) { - case TCP: - LOG.debug("Connecting to server with TCP"); - cb.channelFactory(new ChannelFactory() { - @Override - public Channel newChannel() { - return new NioSocketChannel(); - } - }); - break; - case UDT: - LOG.debug("Connecting to server with UDT"); - cb.channelFactory(NioUdtProvider.BYTE_CONNECTOR) - .option(ChannelOption.SO_REUSEADDR, true); - break; - default: - throw new UnknownTransportProtocolError(transportProtocol); + case TCP: + LOG.debug("Connecting to server with TCP"); + cb.channelFactory(new ChannelFactory() { + @Override + public Channel newChannel() { + return new NioSocketChannel(); + } + }); + break; + case UDT: + LOG.debug("Connecting to server with UDT"); + cb.channelFactory(NioUdtProvider.BYTE_CONNECTOR) + .option(ChannelOption.SO_REUSEADDR, true); + break; + default: + throw new UnknownTransportProtocolError(transportProtocol); } cb.handler(new ChannelInitializer() { protected void initChannel(Channel ch) throws Exception { initChannelPipeline(ch.pipeline(), initialRequest); - } - - ; + }; }); cb.option(ChannelOption.CONNECT_TIMEOUT_MILLIS, proxyServer.getConnectTimeout()); @@ -665,7 +650,7 @@ void read(ConnectionFlow flow, Object msg) { *

* Encrypts the client channel based on our server {@link SSLSession}. *

- *

+ * *

* This does not wait for the handshake to finish so that we can go on and * respond to the CONNECT request. @@ -706,13 +691,14 @@ public void operationComplete( *

* Called to let us know that connection failed. *

- *

+ * *

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

- * - * @param cause the reason that our attempt to connect failed (can be null) + * + * @param cause + * the reason that our attempt to connect failed (can be null) * @return true if we are trying to fall back to another connection */ protected boolean connectionFailed(Throwable cause) @@ -742,7 +728,7 @@ protected boolean connectionFailed(Throwable cause) /** * Set up our connection parameters based on server address and chained * proxies. - * + * * @throws UnknownHostException */ private void setupConnectionParameters() throws UnknownHostException { @@ -773,12 +759,12 @@ private void setupConnectionParameters() throws UnknownHostException { /** * Initialize our {@link ChannelPipeline}. - * + * * @param pipeline * @param httpRequest */ private void initChannelPipeline(ChannelPipeline pipeline, - HttpRequest httpRequest) { + HttpRequest httpRequest) { if (trafficHandler != null) { pipeline.addLast("global-traffic-shaping", trafficHandler); @@ -818,9 +804,10 @@ private void initChannelPipeline(ChannelPipeline pipeline, * Do all the stuff that needs to be done after our {@link ConnectionFlow} * has succeeded. *

- * - * @param shouldForwardInitialRequest whether or not we should forward the initial HttpRequest to - * the server after the connection has been established. + * + * @param shouldForwardInitialRequest + * whether or not we should forward the initial HttpRequest to + * the server after the connection has been established. */ void connectionSucceeded(boolean shouldForwardInitialRequest) { become(AWAITING_INITIAL); @@ -845,14 +832,16 @@ void connectionSucceeded(boolean shouldForwardInitialRequest) { /** * Build an {@link InetSocketAddress} for the given hostAndPort. - * + * * @param hostAndPort - * @param proxyServer the current {@link DefaultHttpProxyServer} + * @param proxyServer + * the current {@link DefaultHttpProxyServer} * @return - * @throws UnknownHostException if hostAndPort could not be resolved + * @throws UnknownHostException + * if hostAndPort could not be resolved */ private static InetSocketAddress addressFor(String hostAndPort, - DefaultHttpProxyServer proxyServer) + DefaultHttpProxyServer proxyServer) throws UnknownHostException { String host; int port; @@ -869,14 +858,12 @@ private static InetSocketAddress addressFor(String hostAndPort, return proxyServer.getServerResolver().resolve(host, port); } - /** - * ************************************************************************ + /*************************************************************************** * Activity Tracking/Statistics - *

+ * * We track statistics on bytes, requests and responses by adding handlers * at the appropriate parts of the pipeline (see initChannelPipeline()). - * ************************************************************************ - */ + **************************************************************************/ private final BytesReadMonitor bytesReadMonitor = new BytesReadMonitor() { @Override protected void bytesRead(int numberOfBytes) {