diff options
Diffstat (limited to 'CSharp/Ivy/IvyPPC/IvyWatcher.cs')
-rw-r--r-- | CSharp/Ivy/IvyPPC/IvyWatcher.cs | 217 |
1 files changed, 217 insertions, 0 deletions
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 @@ +/// <summary> IvyWatcher, A private Class for the Ivy rendezvous
+/// *
+/// </summary>
+/// <author> François-Régis Colin
+/// </author>
+/// <author> <a href="http://www.tls.cena.fr/products/ivy/">http://www.tls.cena.fr/products/ivy/</a>
+/// *
+/// (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.
+/// *
+///
+/// </author>
+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;
+
+ /// <summary> creates an Ivy watcher
+ /// </summary>
+ /// <param name="bus">the bus
+ /// </param>
+ /// <param name="net">the domain
+ ///
+ /// </param>
+ 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);
+ }
+ }
+
+ /// <summary> the behaviour of each thread watching the UDP socket.
+ /// </summary>
+ 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");
+ }
+
+ /// <summary> stops the thread waiting on the broadcast socket
+ /// </summary>
+ 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 |