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) {