package network.platform; import util.NetworkAddress; import util.Parameters; import java.util.TimerTask; import java.util.Timer; import platform.servicesregister.ServicesRegisterManager; import platform.servicesregister.ServiceInUseException; import platform.servicesregister.ServiceClosedException; import network.NetworkEmitterContainer; import network.NetworkReceptorContainer; import platform.plugins.installables.network.DNS.KalimuchoDNS; /** * This service offers a ping mechanism to test if a connexion with a given host is possible directly or not. * This service is used to find a route (by the routing service). * If ping does not reply then a broadcast/multicast message is send to find a route. * @author Dalmau */ public class PingService extends Thread { private PlatformMessagesReceptor boiteDeReponses; private PlatformMessagesEmitter envoi; private NetworkReceptorContainer rec; static private boolean actif = false; private boolean abandon; private NetworkPlatformMessage reponseRecue; private Object semaphore; /** * The service for sending and replyiong to ping messages */ public PingService() { try { NetworkEmitterContainer nec = (NetworkEmitterContainer)ServicesRegisterManager.platformWaitForService(Parameters.NETWORK_EMISSIONS_CONTAINER); envoi = nec.getPlatformMessagesEmitter(); // Mise en place des mecanismes permettant aux plugins de la PF de recevoir les reponses // aux commandes qu'ils envoient aux autres PF ou la PF locale rec = (NetworkReceptorContainer)ServicesRegisterManager.platformWaitForService(Parameters.NETWORK_RECEPTIONS_CONTAINER); boiteDeReponses = rec.getPlatformMessagesReceptor(); semaphore = new Object(); ServicesRegisterManager.registerService(Parameters.NETWORK_PING_SERVICE, this); actif = true; boiteDeReponses.inscription(Parameters.NETWORK_PING_SERVICE); start(); } catch (ServiceInUseException mbiue) { System.err.println("Ping service already created"); } } /** * Stops the PING service (normally this service is stopped only when the platform stops) */ public void stopThread() { if (!actif) return; actif = false; boiteDeReponses.stop(); boiteDeReponses.desinscription(Parameters.NETWORK_PING_SERVICE); } /** * Wait for messages about the ping mechanism.<br> * When a pig message is received, this thread replies to it.<br> * When a ping reply is received, the thread that used the ping mechanism is unlocked. */ @Override public void run() { while (actif) { reponseRecue = boiteDeReponses.retirerMessage(Parameters.NETWORK_PING_SERVICE); if (reponseRecue != null) { String msg = reponseRecue.getContent(); if (msg.equals(Parameters.PING_MESSAGE)) { NetworkPlatformMessage env = new NetworkPlatformMessage(Parameters.NETWORK_PING_SERVICE, reponseRecue.getExpeditorAddress()); env.addContent(Parameters.PING_REPLY_MESSAGE); envoi.postUrgentDirectMessage(env); } else { debloquer(); } } } } /** * Sends a ping and wait for reply or time out * @param adr address to send the ping to * @return true if a reply has been received */ public synchronized boolean testConnexionTo(NetworkAddress adr) { synchronized(semaphore) { NetworkPlatformMessage env = new NetworkPlatformMessage(Parameters.NETWORK_PING_SERVICE, adr.getNormalizedAddress()); env.addContent(Parameters.PING_MESSAGE); long t0 = System.currentTimeMillis(); abandon = false; envoi.postPingMessage(env); Timer delai = new Timer(); delai.schedule(new WaitForTimeOut(), Parameters.MAXIMAL_WAIT_FOR_PING); try { wait(); delai.cancel(); if (abandon) return false; else { try { KalimuchoDNS dns = (KalimuchoDNS)ServicesRegisterManager.lookForService(Parameters.KALIMUCHO_DNS_MANAGER); long t1 = System.currentTimeMillis(); long tDistant = reponseRecue.getDate(); long delta = ((t0 + t1)/2) - tDistant; // valeur a ajouter a l'horloge distante pour avoir l'heure locale //System.out.println("decalage "+delta); dns.adjustRemoteHostClockShift(reponseRecue.getSenderID(), delta, t1-t0); } catch (ServiceClosedException nfe) {} return true; } } catch (InterruptedException ie) { delai.cancel(); return false; } } } private synchronized void debloquer() { notifyAll(); } /** * This methods stops the ping service for waiting for a reply. * It is used when PIG time out occurs or when the pinged host is not reachable (socket error) */ public synchronized void abandonner() { abandon = true; notifyAll(); } private class WaitForTimeOut extends TimerTask { public void run() { abandonner(); } } }