From d27ce639722587647bc812032c55fc8438609705 Mon Sep 17 00:00:00 2001 From: fcolin Date: Thu, 1 Feb 2007 10:03:06 +0000 Subject: Utilisateur : Fcolin Date : 19/05/03 Heure : 15:31 Créé Commentaire: (vss 1) --- CSharp/Ivy/IvyPPC/IvyWatcher.cs | 217 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 217 insertions(+) create mode 100644 CSharp/Ivy/IvyPPC/IvyWatcher.cs diff --git a/CSharp/Ivy/IvyPPC/IvyWatcher.cs b/CSharp/Ivy/IvyPPC/IvyWatcher.cs new file mode 100644 index 0000000..749d837 --- /dev/null +++ b/CSharp/Ivy/IvyPPC/IvyWatcher.cs @@ -0,0 +1,217 @@ +/// IvyWatcher, A private Class for the Ivy rendezvous +/// * +/// +/// François-Régis Colin +/// +/// 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. +/// * +/// +/// +namespace IvyBus +{ + using System; + using System.Threading; + using System.IO; + using System.Net; + using System.Net.Sockets; + using System.Text.RegularExpressions; + using System.Configuration; + using System.Text; + + + class IvyWatcher + { + private bool isMulticastAddress = false; + private Ivy bus; /* master bus controler */ + private Socket broadcast; /* supervision socket */// To do reuseaddr we must use a Socket not a udp client + private String domainaddr; + private int port; + private volatile Thread listenThread; + private IPAddress group; + + /// creates an Ivy watcher + /// + /// the bus + /// + /// the domain + /// + /// + internal IvyWatcher(Ivy bus, String domainaddr, int port) + { + this.bus = bus; + this.domainaddr = domainaddr; + this.port = port; + listenThread = new Thread(new ThreadStart(this.Run)); + // create the MulticastSocket + try + { + group = Dns.GetHostByName(domainaddr).AddressList[0]; + broadcast = new Socket(AddressFamily.InterNetwork, SocketType.Dgram,ProtocolType.Udp); + IPEndPoint EPhost = new IPEndPoint(IPAddress.Any, port); + broadcast.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.Broadcast,1); + broadcast.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress,1); + broadcast.Bind(EPhost); + + //test isMulticastAddress // TODO better check + if ((group.Address & 0xf0000000) == 0xe0000000) + { + isMulticastAddress = true; + broadcast.SetSocketOption(SocketOptionLevel.Udp, SocketOptionName.AddMembership, new MulticastOption( group )); + } + } + catch (IOException e) + { + throw new IvyException("IvyWatcher I/O error" + e); + } + } + + /// the behaviour of each thread watching the UDP socket. + /// + public void Run() + { + traceDebug("beginning of a watcher Thread"); + byte[] buf = new byte[4096]; + int len; + IPEndPoint remoteEP = new IPEndPoint(IPAddress.Any, 0); + EndPoint tempRemoteEP = (EndPoint)remoteEP; + + remoteEP = null; + try + { + bool running = true; + while (running) + { + int port; + try + { + len = broadcast.ReceiveFrom(buf, ref tempRemoteEP); + // I was summoned to leave during the receive + String msg = Encoding.ASCII.GetString(buf); + remoteEP = (IPEndPoint)tempRemoteEP; + IPAddress remotehost = remoteEP.Address; + traceDebug("BUSWATCHER Receive Broadcast from " + Dns.GetHostName() + ":" + remoteEP.Port); + // TODO if ( !isInDomain( remotehost ) ) continue; + String[] st = msg.Split(' '); + if (st.Length != 2) + { + Console.Error.WriteLine("Bad format " + msg); + continue; + } + int version = Int32.Parse(st[0]); + port = Int32.Parse(st[1]); + if (version != Ivy.PROCOCOLVERSION) + { + Console.Error.WriteLine("Ignoring bad protocol version broadcast"); + continue; + } + + if ((bus.applicationPort == port)) + continue; + traceDebug("BUSWATCHER Broadcast de " + Dns.GetHostName() + ":" + remoteEP.Port + " port " + port + " version " + version); + try + { + MyTcpClient socket = new MyTcpClient(remoteEP.Address.ToString(),port); + bus.addClient(socket); + } + catch (Exception e) + { + Console.Error.WriteLine("can't connect to " + remotehost + " port " + port + " \n"+ e.Message); + } + } + catch (IOException jii) + { + running = false; + } + } // while + } + catch (SocketException se) + { + traceDebug( "watcher socket closed" ); + } + catch (IOException ioe) + { + Console.Error.WriteLine( ioe.StackTrace ); + } + traceDebug("end of a watcher thread"); + } + + /// stops the thread waiting on the broadcast socket + /// + internal virtual void stop() + { + lock(this) + { + traceDebug("begining stopping an IvyWatcher"); + Thread t = listenThread; + listenThread = null; + broadcast.Close(); + if (t != null) + { + t.Interrupt(); + } + // it might not even have been created + traceDebug("ending stopping an IvyWatcher"); + } + } + + internal virtual void start() + { + lock(this) + { + String hello = Ivy.PROCOCOLVERSION + " " + bus.applicationPort + "\n"; + listenThread.Start(); + byte[] hellob = Encoding.ASCII.GetBytes( hello ); + IPEndPoint EPhost = new IPEndPoint(group, port); + broadcast.SendTo(hellob,0,EPhost); // notifies our arrival on each domain: protocol version + port + } + } + + + internal static String getDomain(String net) + { + int sep_index = net.LastIndexOf(":"); + if (sep_index != - 1) + { + net = net.Substring(0, (sep_index) - (0)); + } + try + { + net += ".255.255.255"; + Regex exp = new Regex("^(\\d+\\.\\d+\\.\\d+\\.\\d+).*"); + net = exp.Replace(net, "$1"); + } + catch (ArgumentException e) + { + Console.Out.WriteLine("Bad broascat addr " + net); + return null; + } + // out.println("net: "+net); + return net; + } + + internal static int getPort(String net) + { + int sep_index = net.LastIndexOf(":"); + int port = (sep_index == - 1)?Ivy.DEFAULT_PORT:Int32.Parse(net.Substring(sep_index + 1)); + // out.println("net: ["+net+"]\nsep_index: "+sep_index+"\nport: "+port); + return port; + } + + + private void traceDebug(String s) + { + if (bus.Debug) + Console.Out.WriteLine("-->ivywatcher<-- " + s); + } + } + // class IvyWatcher + /* EOF */ +} \ No newline at end of file -- cgit v1.1