/** * IvyWatcher, A private Class for the Ivy rendezvous * * @author Yannick Jestin * @author François-Régis Colin * @author http://www.tls.cena.fr/products/ivy/ * * (C) CENA * * right now, the rendez vous is either an UDP socket or a TCP multicast. * The watcher will answer to * each peer advertising its arrival on the bus. The intrinsics of Unix are so * that the broadcast is done using the same socket, which is not a good * thing. * * CHANGELOG: * 1.2.5: * - getDomain now sends IvyException for malformed broadcast addresses * - uses apache jakarta-regexp instead of gnu-regexp * - throws an IvyException if the broadcast domain cannot be resolved * 1.2.4: * - sends the broadcast before listening to the other's broadcasts. * I can't wait for all the broadcast to be sent before starting the listen * mode, otherwise another agent behaving likewise could be started * meanwhile, and one would not "see" each other. * - (REMOVED) allows the connexion from a remote host with the same port number * it's too complicated to know if the packet is from ourselves... * - deals with the protocol errors in a more efficient way. The goal is not * to loose our connectivity because of a rude agent. * fixes Bug J005 (YJ + JPI) * 1.2.3: * - the packet sending is done in its own thread from now on (PacketSender) * I don't care stopping it, since it can't be blocked. * - checks whether I have been interrupted just after the receive (start() * then stop() immediately). * 1.2.1: * - can be Interrupted during the broadcast Send. I catch the * and do nothing with it. InterruptedIOException * - changed the fill character from 0 to 10, in order to prevent a nasty bug * on Windows XP machines * - fixed a NullPointerException while trying to stop a Thread before having * created it. * 1.0.12: * - setSoTimeout on socket * - the broadcast reader Thread goes volatile * 1.0.10: * - isInDomain() is wrong in multicast. I've removed it * - there was a remanence effect in the datagrampacket buffer. I clean it up after each message * - cleaned up the getDomain() and getPort() code * - close message sends an interruption on all threads for a clean exit * - removed the timeout bug eating all the CPU resources * - now handles a Vector of broadcast listeners */ package fr.dgac.ivy ; import java.lang.Thread; import java.net.*; import java.io.*; import java.util.StringTokenizer; /* import gnu.regexp.*; GNURETOAPACHERE */ import org.apache.regexp.*; import java.util.Vector; import java.util.Enumeration; class IvyWatcher implements Runnable { private static boolean debug = (System.getProperty("IVY_DEBUG")!=null); private boolean isMulticastAddress = false; private Ivy bus; /* master bus controler */ private DatagramSocket broadcast; /* supervision socket */ private InetAddress localhost,loopback; private String domainaddr; private int port; private volatile Thread listenThread; private InetAddress group; /** * creates an Ivy watcher * @param bus the bus * @param net the domain */ IvyWatcher(Ivy bus,String domainaddr,int port) throws IvyException { this.bus = bus; this.domainaddr=domainaddr; this.port=port; listenThread = new Thread(this); // create the MulticastSocket try { group = InetAddress.getByName(domainaddr); broadcast = new MulticastSocket(port); if (group.isMulticastAddress()) { isMulticastAddress = true; ((MulticastSocket)broadcast).joinGroup(group); } broadcast.setSoTimeout(Ivy.TIMEOUTLENGTH); localhost=InetAddress.getLocalHost(); loopback=InetAddress.getByName(null); } catch ( UnknownHostException uhe ) { } catch ( IOException e ) { throw new IvyException("IvyWatcher I/O error" + e ); } } /** * the behaviour of each thread watching the UDP socket. */ public void run() { traceDebug("IvyWatcher Thread started"); // THREADDEBUG Thread thisThread=Thread.currentThread(); traceDebug("beginning of a watcher Thread"); byte buf[] = new byte[256]; DatagramPacket packet=new DatagramPacket(buf, 256); InetAddress remotehost=null; try { while( listenThread==thisThread ) { try { broadcast.receive(packet); if (listenThread!=thisThread) break; // I was summoned to leave during the receive String msg = new String(packet.getData()) ; for (int i=0;iivywatcher<-- "+s); } } // class IvyWatcher /* EOF */