package com.grendelscan.proxy;
import java.io.IOException;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;
import org.apache.http.conn.ClientConnectionManager;
import org.apache.http.params.HttpParams;
import org.apache.http.protocol.HttpContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.grendelscan.commons.ConfigurationManager;
import com.grendelscan.commons.http.apache_overrides.client.ClientUtilities;
import com.grendelscan.commons.http.apache_overrides.client.CustomHttpClient;
public abstract class AbstractProxy
{
private static final Logger LOGGER = LoggerFactory.getLogger(AbstractProxy.class);
protected final ProxyConfig config;
protected ServerSocket serverSocket;
protected boolean running;
protected static int maxThreads;
protected GenericProxyRequestListenerThread[] requestListenerThreads;
protected final Object runningLock = new Object();
protected static CustomHttpClient proxyHttpClient;
protected static ClientConnectionManager ccm;
private static int maxProxyQueueLength;
private static boolean initialized = false;
public AbstractProxy(final ProxyConfig config)
{
this.config = config;
LOGGER.trace("Instantiating proxy on " + getProxyDescription());
}
protected abstract GenericProxyRequestListenerThread createRequestListenerThread();
protected void createSocket() throws IOException
{
LOGGER.trace("Creating socket for proxy on " + getProxyDescription());
try
{
if (config.getBindIP().equals("0.0.0.0"))
{
LOGGER.trace("Starting socket bound to all IPs for proxy on " + getProxyDescription());
serverSocket = new ServerSocket(config.getBindPort(), maxProxyQueueLength);
}
else
{
LOGGER.trace("Starting socket bound to specific IP for proxy on " + getProxyDescription());
InetAddress bindInetAddress = InetAddress.getByName(config.getBindIP());
serverSocket = new ServerSocket(config.getBindPort(), maxProxyQueueLength, bindInetAddress);
}
serverSocket.setSoTimeout(500);
}
catch (IOException e)
{
LOGGER.error("Problem opening proxy socket: " + e.toString(), e);
Scan.getInstance().displayMessage("Error:", "The " + getName() + " failed to start. You may need to change\n" + "some parameters. The error message is: \n\n" + e.getMessage());
throw e;
}
}
// private HttpParams createServerHttpParams()
// {
//
// // prepare parameters
// HttpParams params = new BasicHttpParams();
//
// ConnPerRouteBean maxConnectionsPerRoute = new ConnPerRouteBean();
// params.setParameter(ConnManagerPNames.MAX_CONNECTIONS_PER_ROUTE, maxConnectionsPerRoute);
// params.setIntParameter(ConnManagerPNames.MAX_TOTAL_CONNECTIONS, 5);
// HttpProtocolParams.setVersion(params, HttpVersion.HTTP_1_1);
// HttpProtocolParams.setContentCharset(params, "UTF-8");
// params.setBooleanParameter(CoreConnectionPNames.STALE_CONNECTION_CHECK, false);
// params.setBooleanParameter(ClientPNames.HANDLE_REDIRECTS, false);
// params.setBooleanParameter(CoreConnectionPNames.TCP_NODELAY, true);
// params.setParameter(CoreProtocolPNames.ORIGIN_SERVER, GrendelScan.versionHttpText);
// params.setIntParameter(CoreConnectionPNames.SO_TIMEOUT, 5000);
// params.setBooleanParameter(CoreProtocolPNames.USE_EXPECT_CONTINUE, false);
// if (scanSettings.getUseUpstreamProxy())
// {
// HttpHost proxy = new HttpHost(scanSettings.getUpstreamProxyAddress(), scanSettings.getUpstreamProxyPort());
// params.setParameter(ConnRoutePNames.DEFAULT_PROXY, proxy);
// }
// return params;
// }
// private static void initSSL()
// {
// SchemeRegistry schemeRegistry = new SchemeRegistry();
// SSLSocketFactory secureSocketFactory = null;
// KeyStore trustStore;
// try
// {
// trustStore = KeyStore.getInstance(KeyStore.getDefaultType());
// secureSocketFactory = new SSLSocketFactory(trustStore);
// }
// catch (KeyStoreException e)
// {
// Debug.errDebug("Problem initializing KeyStore: " + e.toString(), e);
// System.exit(1);
// }
// catch (NoSuchAlgorithmException e)
// {
// Debug.errDebug("Problem initializing KeyStore: " + e.toString(), e);
// System.exit(1);
// }
// catch (KeyManagementException e)
// {
// Debug.errDebug("Problem initializing KeyStore: " + e.toString(), e);
// System.exit(1);
// }
// catch (UnrecoverableKeyException e)
// {
// Debug.errDebug("Problem initializing KeyStore: " + e.toString(), e);
// System.exit(1);
// }
//
// PlainSocketFactory plainSocketFactory = PlainSocketFactory.getSocketFactory();
//
// schemeRegistry.register(new Scheme("https", secureSocketFactory, 443));
// schemeRegistry.register(new Scheme("http", plainSocketFactory, 80));
// }
public ProxyConfig getConfig()
{
return config;
}
public abstract String getName();
public String getProxyDescription()
{
return config.getBindIP() + ":" + config.getBindPort();
}
public CustomHttpClient getProxyHttpClient()
{
return proxyHttpClient;
}
public abstract AbstractProxyRequestHandler getRequestHandler(Socket socket, boolean ssl, int sslPort);
protected synchronized void initParams()
{
if (!initialized)
{
maxThreads = ConfigurationManager.getInt("proxy.thread_count", 5);
HttpParams clientParams = ClientUtilities.createHttpParams();
HttpContext clientContext = ClientUtilities.createHttpContext();
ccm = ClientUtilities.createClientConnectionManager(10, 5); // need to put these in a config file
proxyHttpClient = new CustomHttpClient(ccm, clientParams, clientContext);
maxProxyQueueLength = ConfigurationManager.getInt("proxy.max_queue_length", 20);
initialized = true;
}
}
protected void initThreads()
{
requestListenerThreads = new GenericProxyRequestListenerThread[maxThreads];
for (int index = 0; index < maxThreads; index++)
{
GenericProxyRequestListenerThread listenerThread = createRequestListenerThread();
listenerThread.setName("ProxyThread-" + getName() + " -- " + index);
requestListenerThreads[index] = listenerThread;
listenerThread.start();
}
}
public boolean isRunning()
{
return running;
}
public abstract boolean isSSL();
public void startProxy()
{
LOGGER.debug("Starting proxy for " + getProxyDescription());
synchronized (runningLock)
{
if (running)
{
return;
}
initParams();
try
{
createSocket();
running = true;
initThreads();
}
catch (IOException e)
{
LOGGER.error("Failed to start proxy for " + getProxyDescription(), e);
}
}
}
public void stopProxy()
{
LOGGER.debug("Stopping proxy for " + getProxyDescription());
synchronized (runningLock)
{
if (!running)
{
LOGGER.trace("Proxy already stopped");
return;
}
LOGGER.trace("Proxy stopped");
running = false;
}
// ccm.shutdown();
try
{
LOGGER.trace("Trying to close server socket");
if (serverSocket != null)
{
serverSocket.close();
}
}
catch (IOException e)
{
LOGGER.error("Problem closing proxy socket: " + e.toString(), e);
}
for (GenericProxyRequestListenerThread requestListenerThread : requestListenerThreads)
{
LOGGER.trace("Shutting down thread (" + requestListenerThread.getName() + ") for " + getProxyDescription());
requestListenerThread.shutdown();
}
}
}