package com.limegroup.gnutella.browser;
import java.io.IOException;
import java.util.concurrent.Executor;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.http.HttpEntityEnclosingRequest;
import org.apache.http.HttpException;
import org.apache.http.HttpRequest;
import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.nio.entity.ConsumingNHttpEntity;
import org.apache.http.nio.entity.NStringEntity;
import org.apache.http.nio.protocol.SimpleNHttpRequestHandler;
import org.apache.http.protocol.HttpContext;
import org.limewire.concurrent.ExecutorsHelper;
import org.limewire.http.BasicHttpAcceptor;
import org.limewire.http.auth.AuthenticationInterceptor;
import org.limewire.inject.EagerSingleton;
import com.google.inject.Inject;
import com.limegroup.gnutella.Constants;
import com.limegroup.gnutella.util.LimeWireUtils;
@EagerSingleton
public class LocalHTTPAcceptor extends BasicHttpAcceptor {
private static final Log LOG = LogFactory.getLog(LocalHTTPAcceptor.class);
private static final String[] SUPPORTED_METHODS = new String[] { "GET",
"HEAD", "POST", "DELETE"};
private final Executor magnetExecutor = ExecutorsHelper.newProcessingQueue("magnet-handler");
/** Magnet request for a default action on parameters */
// private static final String MAGNET_DEFAULT = "/magnet10/default.js?";
/** Magnet request for a paused response */
// private static final String MAGNET_PAUSE = "/magnet10/pause";
/** Start of Magnet URI */
private static final String MAGNET = "magnet:?";
/** Magnet detail command */
private static final String MAGNET_DETAIL = "magcmd/detail?";
private String lastCommand;
private long lastCommandTime;
private long MIN_REQUEST_INTERVAL = 1500;
private final ExternalControl externalControl;
@Inject
public LocalHTTPAcceptor(ExternalControl externalControl,
AuthenticationInterceptor requestAuthenticator) {
super(createDefaultParams(LimeWireUtils.getHttpServer(), Constants.TIMEOUT),
requestAuthenticator, SUPPORTED_METHODS);
this.externalControl = externalControl;
registerHandler("magnet:", new MagnetCommandRequestHandler());
registerHandler("/magnet10/default.js", new MagnetCommandRequestHandler());
registerHandler("/magnet10/pause", new MagnetPauseRequestHandler());
registerHandler("/magcmd/detail", new MagnetDetailRequestHandler());
// TODO figure out which files we want to serve from the local file system
//registerHandler("*", new FileRequestHandler(new File("root"), new BasicMimeTypeProvider()));
}
@Inject
void register(org.limewire.lifecycle.ServiceRegistry registry) {
registry.register(this);
}
@Override
public String getServiceName() {
return org.limewire.i18n.I18nMarker.marktr("Magnet Processor");
}
private class MagnetCommandRequestHandler extends SimpleNHttpRequestHandler {
public ConsumingNHttpEntity entityRequest(HttpEntityEnclosingRequest request,
HttpContext context) throws HttpException, IOException {
return null;
}
@Override
public void handle(HttpRequest request, HttpResponse response,
HttpContext context) throws HttpException, IOException {
final String uri = request.getRequestLine().getUri();
magnetExecutor.execute(new Runnable() {
public void run() {
try {
triggerMagnetHandling(uri);
} catch(IOException ignored) {}
}
});
}
}
private class MagnetPauseRequestHandler extends SimpleNHttpRequestHandler {
public ConsumingNHttpEntity entityRequest(HttpEntityEnclosingRequest request,
HttpContext context) throws HttpException, IOException {
return null;
}
@Override
public void handle(HttpRequest request, HttpResponse response,
HttpContext context) throws HttpException, IOException {
response.setStatusCode(HttpStatus.SC_NO_CONTENT);
magnetExecutor.execute(new Runnable() {
public void run() {
try {
Thread.sleep(2500);
} catch (InterruptedException e) {
}
}
});
}
}
private static class MagnetDetailRequestHandler extends SimpleNHttpRequestHandler {
public ConsumingNHttpEntity entityRequest(HttpEntityEnclosingRequest request,
HttpContext context) throws HttpException, IOException {
return null;
}
@Override
public void handle(HttpRequest request, HttpResponse response,
HttpContext context) throws HttpException, IOException {
String uri = request.getRequestLine().getUri();
int i = uri.indexOf(MAGNET_DETAIL);
String command = uri.substring(i + MAGNET_DETAIL.length());
String page = MagnetHTML.buildMagnetDetailPage(command);
NStringEntity entity = new NStringEntity(page);
entity.setContentType("text/html");
response.setEntity(entity);
}
}
private synchronized void triggerMagnetHandling(String uri)
throws IOException {
int i = uri.indexOf("?");
if (i == -1) {
throw new IOException("Invalid command");
}
String command = uri.substring(i + 1);
// suppress duplicate requests from some browsers
long currentTime = System.currentTimeMillis();
if (!command.equals(lastCommand) || (currentTime - lastCommandTime) >= MIN_REQUEST_INTERVAL) {
// trigger an operation
externalControl.handleMagnetRequest(MAGNET + command);
lastCommand = command;
lastCommandTime = currentTime;
} else {
LOG.warn("Ignoring duplicate request: " + command);
}
}
}