package com.limegroup.gnutella;
import java.net.InetAddress;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.limewire.collection.Comparators;
import org.limewire.core.settings.FilterSettings;
import com.google.inject.Inject;
import com.google.inject.Provider;
import com.google.inject.Singleton;
import com.limegroup.gnutella.connection.RoutedConnection;
import com.limegroup.gnutella.filters.IPFilter;
import com.limegroup.gnutella.filters.SpamFilter;
import com.limegroup.gnutella.filters.SpamFilterFactory;
import com.limegroup.gnutella.filters.URNFilter;
import com.limegroup.gnutella.filters.response.ResponseFilterFactory;
import com.limegroup.gnutella.messages.Message;
import com.limegroup.gnutella.search.SearchResultHandler;
@Singleton
public class SpamServicesImpl implements SpamServices, SpamFilter.LoadCallback {
private static final Log LOG = LogFactory.getLog(SpamServicesImpl.class);
private final Provider<ConnectionManager> connectionManager;
private final Provider<IPFilter> ipFilter;
private final Provider<URNFilter> urnFilter;
private final SpamFilterFactory spamFilterFactory;
private final SearchResultHandler searchResultHandler;
private final ResponseFilterFactory responseFilterFactory;
private volatile SpamFilter personalFilter;
private final AtomicInteger filtersLoading;
@Inject
public SpamServicesImpl(Provider<ConnectionManager> connectionManager,
Provider<IPFilter> ipFilter, Provider<URNFilter> urnFilter,
SpamFilterFactory spamFilterFactory,
SearchResultHandler searchResultHandler,
ResponseFilterFactory responseFilterFactory) {
this.connectionManager = connectionManager;
this.ipFilter = ipFilter;
this.urnFilter = urnFilter;
this.spamFilterFactory = spamFilterFactory;
this.searchResultHandler = searchResultHandler;
this.responseFilterFactory = responseFilterFactory;
personalFilter = spamFilterFactory.createPersonalFilter();
filtersLoading = new AtomicInteger(0);
}
@Override
public void spamFilterLoaded() {
// Wait until all filters have loaded
if(filtersLoading.decrementAndGet() == 0)
adjustSpamFilters();
}
@Override
public void adjustSpamFilters() {
LOG.trace("Adjusting spam filters");
personalFilter = spamFilterFactory.createPersonalFilter();
searchResultHandler.setResponseFilter(responseFilterFactory.createResponseFilter());
// Replace the route filter on each connection
for(RoutedConnection c : connectionManager.get().getConnections()) {
if(ipFilter.get().allow(c.getAddress())) {
c.setRouteFilter(spamFilterFactory.createRouteFilter());
} else {
// If the connection isn't allowed now, close it.
c.close();
}
}
// TODO: notify DownloadManager & UploadManager about new banned IP ranges
}
@Override
public void reloadIPFilter() {
LOG.trace("Reloading IP filter");
filtersLoading.addAndGet(1);
ipFilter.get().refreshHosts(this);
}
@Override
public void reloadSpamFilters() {
LOG.trace("Reloading spam filters");
filtersLoading.addAndGet(2);
ipFilter.get().refreshHosts(this);
urnFilter.get().refreshURNs(this);
}
@Override
public boolean isAllowed(InetAddress host) {
return ipFilter.get().allow(host.getAddress());
}
@Override
public void blockHost(String host) {
// FIXME move into IPFilter
// FIXME synchronize access to setting properly?
String[] bannedIPs = FilterSettings.BLACK_LISTED_IP_ADDRESSES.get();
Arrays.sort(bannedIPs, Comparators.stringComparator());
if (Arrays.binarySearch(bannedIPs, host, Comparators.stringComparator()) < 0) {
String[] more_banned = new String[bannedIPs.length + 1];
System.arraycopy(bannedIPs, 0, more_banned, 0, bannedIPs.length);
more_banned[bannedIPs.length] = host;
FilterSettings.BLACK_LISTED_IP_ADDRESSES.set(more_banned);
reloadSpamFilters();
}
}
@Override
public void unblockHost(String host) {
// FIXME move into IPFilter
// FIXME synchronize access to setting properly?
String[] bannedIPs = FilterSettings.BLACK_LISTED_IP_ADDRESSES.get();
List<String> bannedList = Arrays.asList(bannedIPs);
if (bannedList.remove(host)) {
FilterSettings.BLACK_LISTED_IP_ADDRESSES.set(bannedList.toArray(new String[0]));
reloadSpamFilters();
}
}
@Override
public boolean isPersonalSpam(Message m) {
return !personalFilter.allow(m);
}
}