package call; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.HashSet; import java.util.List; import java.util.Set; public class ContactScanner implements Runnable { private static final List<String> hostsDefault = Arrays.asList(Config.DEFAULT_CONTACT_HOSTS); private static Set<String> hostsOfInterest; private static Set<String> hostsMostSeen; private static boolean active; private static Thread scannerThread; private static final int MIN_WAITTIME = 30_000; private static final int MAX_WAITTIME = 300_000; private static int waittime; public ContactScanner() { if (hostsOfInterest == null) { hostsOfInterest = new HashSet<>(); String[] hosts = Util.split(";", Config.CUSTOM_CONTACTS.getStringValue()); hostsOfInterest.addAll(Util.asSet(hosts)); } if (hostsMostSeen == null) { hostsMostSeen = new HashSet<>(); String[] hosts = Util.split(";", Config.CONNECTED_CONTACTS.getStringValue()); hostsMostSeen.addAll(Util.asSet(hosts)); } } @Override public void run() { scannerThread = Thread.currentThread(); active = true; waittime = MIN_WAITTIME; while (active) { boolean hasBeenInterrupted = scan(); if (waittime < MAX_WAITTIME) waittime += 60_000; if (!hasBeenInterrupted) { for (int i = 0; i < waittime && !Thread.interrupted(); i += 1000) { Util.sleep(1000); } } } } public static void scanNow() { scannerThread.interrupt(); waittime = MIN_WAITTIME; } private static boolean scan() { List<Thread> threads = new ArrayList<>(); for (String host : hostsMostSeen) { threads.add(scan(host)); } threads.add(scan(hostsDefault)); threads.add(scan(hostsOfInterest)); boolean interrupted = Util.joinThreads(threads); if (interrupted) { Util.interruptThreads(threads); } threads = null; System.gc(); return interrupted; } private static Thread scan(final String host) { return scan(Arrays.asList(new String[] { host })); } private static Thread scan(final Collection<String> hosts) { Thread thread = new Thread(new Runnable() { @Override public void run() { try { for (int i = 0; i <= 5; ++i) { for (String host : hosts) { checkContact(host, Config.DEFAULT_PORT + 10 * i); } } } catch (InterruptedException e) { Util.log(Thread.currentThread().toString(), "interrupted..."); } } }, "ContactScanner -> scan()"); thread.start(); return thread; } private static void checkContact(final String host, final int port) throws InterruptedException { if (Thread.interrupted()) // Clears interrupted status! throw new InterruptedException(); try { StatusClient client = new StatusClient(host, port); client.close(); ContactList.addContact(client.getContact()); ContactList.setOnline(client.getContact(), true); addHostMostSeen(client.getContact().getHost()); } catch (Exception e) {} } private static void addHostMostSeen(String host) { if (!hostsMostSeen.contains(host)) { hostsMostSeen.add(host); Config.CONNECTED_CONTACTS.setStringValue(Util.join(hostsMostSeen, ";")); } } public static void addHostOfInterest(String host) { if (!hostsDefault.contains(host)) { hostsOfInterest.add(host); Config.CUSTOM_CONTACTS.setStringValue(Util.join(hostsOfInterest, ";")); } } public void close() { active = false; } }