package com.limegroup.gnutella.connection; import java.util.Collection; import org.limewire.collection.Cancellable; import org.limewire.io.IpPort; import com.google.inject.Inject; import com.google.inject.Provider; import com.limegroup.gnutella.ConnectionServices; import com.limegroup.gnutella.MessageListener; import com.limegroup.gnutella.ReplyHandler; import com.limegroup.gnutella.UniqueHostPinger; import com.limegroup.gnutella.UDPService; import com.limegroup.gnutella.messages.Message; import com.limegroup.gnutella.messages.PingRequest; import com.limegroup.gnutella.messages.PingRequestFactory; public class UDPConnectionCheckerImpl implements UDPConnectionChecker { private final ConnectionServices connectionServices; private final Provider<UDPService> udpService; private final Provider<UniqueHostPinger> uniqueHostPinger; private final PingRequestFactory pingRequestFactory; @Inject public UDPConnectionCheckerImpl(ConnectionServices connectionServices, Provider<UDPService> udpService, Provider<UniqueHostPinger> uniqueHostPinger, PingRequestFactory pingRequestFactory) { this.connectionServices = connectionServices; this.udpService = udpService; this.uniqueHostPinger = uniqueHostPinger; this.pingRequestFactory = pingRequestFactory; } public boolean udpIsDead() { PingRequest ping = pingRequestFactory.createUDPPing(); Collection<IpPort> hosts = connectionServices.getPreferencedHosts(false, "en", 50); UDPChecker checker = new UDPChecker(); // send some hosts to be ranked uniqueHostPinger.get().rank(hosts, checker, checker, ping); long now = System.currentTimeMillis(); synchronized (checker) { try { // since there may be other udp packets backed up to be sent, // check every second if we have received something, and if so // cancel the hosts we sent. for (int i = 0; i < 5; i++) { checker.wait(1000); if (udpService.get().getLastReceivedTime() > now) { checker.received = true; return false; } } } catch (InterruptedException ignored) { } } return !checker.received; } private static class UDPChecker implements MessageListener, Cancellable { volatile boolean received; public boolean isCancelled() { return received; } public void processMessage(Message m, ReplyHandler handler) { received = true; synchronized (this) { notify(); } } public void registered(byte[] guid) { } public void unregistered(byte[] guid) { } } }