mirror of
https://github.com/zxing/zxing.git
synced 2025-03-05 20:48:51 -08:00
More drastic changes to prevent CLOSE_WAIT - defensive socket settings, ban a troublesome IP
git-svn-id: https://zxing.googlecode.com/svn/trunk@2238 59b500cc-1b3d-0410-9834-0bbf25fbcc57
This commit is contained in:
parent
bd1d0c4bef
commit
65efebdc97
|
@ -46,6 +46,10 @@ import org.apache.http.client.methods.HttpGet;
|
||||||
import org.apache.http.client.methods.HttpUriRequest;
|
import org.apache.http.client.methods.HttpUriRequest;
|
||||||
import org.apache.http.conn.ClientConnectionManager;
|
import org.apache.http.conn.ClientConnectionManager;
|
||||||
import org.apache.http.impl.client.DefaultHttpClient;
|
import org.apache.http.impl.client.DefaultHttpClient;
|
||||||
|
import org.apache.http.impl.conn.BasicClientConnectionManager;
|
||||||
|
import org.apache.http.params.BasicHttpParams;
|
||||||
|
import org.apache.http.params.CoreConnectionPNames;
|
||||||
|
import org.apache.http.params.HttpParams;
|
||||||
import org.apache.http.util.EntityUtils;
|
import org.apache.http.util.EntityUtils;
|
||||||
|
|
||||||
import java.awt.color.CMMException;
|
import java.awt.color.CMMException;
|
||||||
|
@ -63,7 +67,6 @@ import java.util.EnumMap;
|
||||||
import java.util.EnumSet;
|
import java.util.EnumSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.concurrent.TimeUnit;
|
|
||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
|
@ -102,14 +105,12 @@ public final class DecodeServlet extends HttpServlet {
|
||||||
}
|
}
|
||||||
|
|
||||||
private DiskFileItemFactory diskFileItemFactory;
|
private DiskFileItemFactory diskFileItemFactory;
|
||||||
private HttpClient client;
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void init(ServletConfig servletConfig) {
|
public void init(ServletConfig servletConfig) {
|
||||||
Logger logger = Logger.getLogger("com.google.zxing");
|
Logger logger = Logger.getLogger("com.google.zxing");
|
||||||
logger.addHandler(new ServletContextLogHandler(servletConfig.getServletContext()));
|
logger.addHandler(new ServletContextLogHandler(servletConfig.getServletContext()));
|
||||||
diskFileItemFactory = new DiskFileItemFactory();
|
diskFileItemFactory = new DiskFileItemFactory();
|
||||||
client = new DefaultHttpClient();
|
|
||||||
log.info("DecodeServlet configured");
|
log.info("DecodeServlet configured");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -143,6 +144,14 @@ public final class DecodeServlet extends HttpServlet {
|
||||||
HttpUriRequest getRequest = new HttpGet(imageURI);
|
HttpUriRequest getRequest = new HttpGet(imageURI);
|
||||||
getRequest.addHeader("Connection", "close"); // Avoids CLOSE_WAIT socket issue?
|
getRequest.addHeader("Connection", "close"); // Avoids CLOSE_WAIT socket issue?
|
||||||
|
|
||||||
|
HttpParams params = new BasicHttpParams();
|
||||||
|
DefaultHttpClient.setDefaultHttpParams(params);
|
||||||
|
params.setIntParameter(CoreConnectionPNames.SO_LINGER, 5); // Avoids CLOSE_WAIT socket issue?
|
||||||
|
params.setIntParameter(CoreConnectionPNames.SO_TIMEOUT, 5000);
|
||||||
|
params.setIntParameter(CoreConnectionPNames.CONNECTION_TIMEOUT, 5000);
|
||||||
|
|
||||||
|
ClientConnectionManager connectionManager = new BasicClientConnectionManager();
|
||||||
|
HttpClient client = new DefaultHttpClient(connectionManager, params);
|
||||||
try {
|
try {
|
||||||
|
|
||||||
HttpResponse getResponse;
|
HttpResponse getResponse;
|
||||||
|
@ -194,9 +203,7 @@ public final class DecodeServlet extends HttpServlet {
|
||||||
}
|
}
|
||||||
|
|
||||||
} finally {
|
} finally {
|
||||||
ClientConnectionManager connectionManager = client.getConnectionManager();
|
connectionManager.shutdown();
|
||||||
connectionManager.closeExpiredConnections();
|
|
||||||
connectionManager.closeIdleConnections(1, TimeUnit.SECONDS);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -390,7 +397,6 @@ public final class DecodeServlet extends HttpServlet {
|
||||||
@Override
|
@Override
|
||||||
public void destroy() {
|
public void destroy() {
|
||||||
log.config("DecodeServlet shutting down...");
|
log.config("DecodeServlet shutting down...");
|
||||||
client.getConnectionManager().shutdown();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,6 +27,7 @@ import javax.servlet.http.HttpServletResponse;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.net.InetAddress;
|
import java.net.InetAddress;
|
||||||
import java.net.UnknownHostException;
|
import java.net.UnknownHostException;
|
||||||
|
import java.util.Arrays;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
@ -44,9 +45,11 @@ public final class DoSFilter implements Filter {
|
||||||
private static final int MAX_ACCESSES_PER_IP_PER_TIME = 10;
|
private static final int MAX_ACCESSES_PER_IP_PER_TIME = 10;
|
||||||
private static final long MAX_ACCESS_INTERVAL_MSEC = 10L * 1000L;
|
private static final long MAX_ACCESS_INTERVAL_MSEC = 10L * 1000L;
|
||||||
private static final long UNBAN_INTERVAL_MSEC = 60L * 60L * 1000L;
|
private static final long UNBAN_INTERVAL_MSEC = 60L * 60L * 1000L;
|
||||||
|
public static final String BAD_IPS_INIT_PARAM = "bad.ips";
|
||||||
|
|
||||||
private final IPTrie numRecentAccesses;
|
private final IPTrie numRecentAccesses;
|
||||||
private final Timer timer;
|
private final Timer timer;
|
||||||
|
private final Set<String> badIPAddresses;
|
||||||
private final Set<String> bannedIPAddresses;
|
private final Set<String> bannedIPAddresses;
|
||||||
private ServletContext context;
|
private ServletContext context;
|
||||||
|
|
||||||
|
@ -54,6 +57,7 @@ public final class DoSFilter implements Filter {
|
||||||
numRecentAccesses = new IPTrie();
|
numRecentAccesses = new IPTrie();
|
||||||
timer = new Timer("DosFilter reset timer");
|
timer = new Timer("DosFilter reset timer");
|
||||||
bannedIPAddresses = Collections.synchronizedSet(new HashSet<String>());
|
bannedIPAddresses = Collections.synchronizedSet(new HashSet<String>());
|
||||||
|
badIPAddresses = new HashSet<String>();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -61,6 +65,11 @@ public final class DoSFilter implements Filter {
|
||||||
context = filterConfig.getServletContext();
|
context = filterConfig.getServletContext();
|
||||||
timer.scheduleAtFixedRate(new ResetTask(), 0L, MAX_ACCESS_INTERVAL_MSEC);
|
timer.scheduleAtFixedRate(new ResetTask(), 0L, MAX_ACCESS_INTERVAL_MSEC);
|
||||||
timer.scheduleAtFixedRate(new UnbanTask(), 0L, UNBAN_INTERVAL_MSEC);
|
timer.scheduleAtFixedRate(new UnbanTask(), 0L, UNBAN_INTERVAL_MSEC);
|
||||||
|
badIPAddresses.clear();
|
||||||
|
String badIPsString = filterConfig.getInitParameter(BAD_IPS_INIT_PARAM);
|
||||||
|
if (badIPsString != null) {
|
||||||
|
badIPAddresses.addAll(Arrays.asList(badIPsString.split(",")));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -77,7 +86,7 @@ public final class DoSFilter implements Filter {
|
||||||
|
|
||||||
private boolean isBanned(ServletRequest request) {
|
private boolean isBanned(ServletRequest request) {
|
||||||
String remoteIPAddressString = request.getRemoteAddr();
|
String remoteIPAddressString = request.getRemoteAddr();
|
||||||
if (bannedIPAddresses.contains(remoteIPAddressString)) {
|
if (bannedIPAddresses.contains(remoteIPAddressString) || badIPAddresses.contains(remoteIPAddressString)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
InetAddress remoteIPAddress;
|
InetAddress remoteIPAddress;
|
||||||
|
@ -100,6 +109,7 @@ public final class DoSFilter implements Filter {
|
||||||
timer.cancel();
|
timer.cancel();
|
||||||
numRecentAccesses.clear();
|
numRecentAccesses.clear();
|
||||||
bannedIPAddresses.clear();
|
bannedIPAddresses.clear();
|
||||||
|
badIPAddresses.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
private final class ResetTask extends TimerTask {
|
private final class ResetTask extends TimerTask {
|
||||||
|
|
|
@ -24,6 +24,10 @@
|
||||||
<filter>
|
<filter>
|
||||||
<filter-name>DoSFilter</filter-name>
|
<filter-name>DoSFilter</filter-name>
|
||||||
<filter-class>com.google.zxing.web.DoSFilter</filter-class>
|
<filter-class>com.google.zxing.web.DoSFilter</filter-class>
|
||||||
|
<init-param>
|
||||||
|
<param-name>bad.ips</param-name>
|
||||||
|
<param-value>69.89.31.60,2.95.142.74</param-value> <!-- Causes weird CLOSE_WAIT thread hangs -->
|
||||||
|
</init-param>
|
||||||
</filter>
|
</filter>
|
||||||
|
|
||||||
<filter-mapping>
|
<filter-mapping>
|
||||||
|
|
Loading…
Reference in a new issue