/**
* 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 */