From 5e310bef48ed719d15d88aafb9b92e674cb42b96 Mon Sep 17 00:00:00 2001 From: fcolin Date: Mon, 18 Oct 2010 15:42:04 +0000 Subject: utilisation de socket IPV6 si le domain contient un multicast IPV6 genre FF02::1 --- Ivy/IvyWatcher.cs | 261 ++++++++++++++++++++++++++++-------------------------- 1 file changed, 135 insertions(+), 126 deletions(-) (limited to 'Ivy/IvyWatcher.cs') diff --git a/Ivy/IvyWatcher.cs b/Ivy/IvyWatcher.cs index 8764a28..f239b99 100644 --- a/Ivy/IvyWatcher.cs +++ b/Ivy/IvyWatcher.cs @@ -15,8 +15,8 @@ namespace IvyBus using System.Text.RegularExpressions; using System.Configuration; using System.Text; - using System.Diagnostics; - using IvyBus.Properties; + using System.Diagnostics; + using IvyBus.Properties; /// IvyWatcher, A private Class for the Ivy rendezvous /// @@ -26,13 +26,14 @@ namespace IvyBus /// that the broadcast is done using the same socket, which is not a good /// thing. /// - internal class IvyWatcher: IDisposable + internal class IvyWatcher //: IDisposable { private Ivy bus; /* master bus controler */ private int port; private volatile Thread listenThread; private IPAddress group; - private IvyUDPStream stream; + private IvyUDPStream stream; + private bool ipv6; /// creates an Ivy watcher /// @@ -42,38 +43,46 @@ namespace IvyBus /// /// the port number /// - internal IvyWatcher(Ivy bus, String domainaddr, int port) + internal IvyWatcher(Ivy bus, String domainaddr, int port, bool _ipv6) { - int multicast_ttl = 64; // region + int multicast_ttl = 64; // region this.bus = bus; this.port = port; + this.ipv6 = _ipv6; listenThread = new Thread(new ThreadStart(this.Run)); listenThread.Name = "Ivy UDP Listener Thread"; try { group = IPAddress.Parse(domainaddr); - /* supervision socket */ - // To do reuseaddr we must use a Socket not a udp client - Socket broadcast = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp); - IPEndPoint EPhost = new IPEndPoint(IPAddress.Any, port); + /* supervision socket */ + // To do reuseaddr we must use a Socket not a udp client + Socket broadcast = new Socket(ipv6 ? AddressFamily.InterNetworkV6 : AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp); + IPEndPoint EPhost = new IPEndPoint(ipv6 ? IPAddress.IPv6Any : IPAddress.Any, port); broadcast.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.Broadcast,true); broadcast.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress,true); broadcast.Bind(EPhost); //test isMulticastAddress // TODO better check - //if ( group.IsIPv6Multicast ) //yes but in IPV4 how to do - byte[] addr = group.GetAddressBytes(); - if ((addr[0] & 0xf0) == 0xe0) - { - broadcast.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.MulticastTimeToLive, multicast_ttl); - broadcast.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.AddMembership, new MulticastOption(group)); - - } - // TODO support the Two protocol - if (bus.protocolVersion == 4) - stream = new IvyUDPStreamV4(broadcast); - else - stream = new IvyUDPStreamV3(broadcast); + if (group.IsIPv6Multicast) //IPV6 multicast + { + broadcast.SetSocketOption(SocketOptionLevel.IPv6, SocketOptionName.MulticastTimeToLive, multicast_ttl); + broadcast.SetSocketOption(SocketOptionLevel.IPv6, SocketOptionName.AddMembership, new IPv6MulticastOption(group)); + } + else + { + byte[] addr = group.GetAddressBytes();//yes but in IPV4 how to do better + if ((addr[0] & 0xf0) == 0xe0) + { + broadcast.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.MulticastTimeToLive, multicast_ttl); + broadcast.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.AddMembership, new MulticastOption(group)); + + } + } + // TODO support the Two protocol + if (bus.protocolVersion == 4) + stream = new IvyUDPStreamV4(broadcast); + else + stream = new IvyUDPStreamV3(broadcast); } catch (IOException e) { @@ -82,95 +91,95 @@ namespace IvyBus } /// - /// the behaviour of each thread watching the UDP socket. + /// the behaviour of each thread watching the UDP socket. /// private void Run() { - Ivy.traceProtocol(Resources.IvyWatcher, "beginning of a watcher Thread"); - - try - { - bool running = true; - while (running) - { - int version; - int appPort; - string appId; - string appName; - IPEndPoint remoteEP; - - stream.receiveMsg(out remoteEP, out version, out appPort, out appId, out appName); - IPAddress remotehost = remoteEP.Address; - - Ivy.traceProtocol(Resources.IvyWatcher, Resources.WatcherReceive + Dns.GetHostEntry(remotehost).HostName + ":" + remoteEP.Port); - - //TODO if ( !isInDomain( remotehost ) ) continue; - - if (version != stream.ProtocolVersion) - { - Ivy.traceError(Resources.IvyWatcher, Resources.BadVersion + version + " expected " + stream.ProtocolVersion); - continue; - } - - /* check if we received our own message. SHOULD ALSO TEST THE HOST */ - if (appId == bus.AppId) - continue; - if ((appPort == bus.applicationPort) && (remotehost.Equals(bus.applicationHost))) - continue; - - Ivy.traceProtocol(Resources.IvyWatcher, "reponse au Broadcast de " + Dns.GetHostEntry(remotehost).HostName + ":" + remoteEP.Port + " port " + appPort + - " version " + version + - " id " + appId + - " name " + appName); - - try - { - Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); - IPEndPoint hostEndPoint = new IPEndPoint(remoteEP.Address, appPort); - socket.Blocking = true; - socket.Connect(hostEndPoint); - IvyClient client = new IvyClient(this.bus, socket, appName, appPort); - client.SendBindings(); - } - catch (SocketException e) - { - Ivy.traceError(Resources.IvyWatcher, Resources.WatcherConnectError + remotehost + " port " + appPort + " \n" + e.Message); - } + Ivy.traceProtocol(Resources.IvyWatcher, "beginning of a watcher Thread"); - } // while - } - catch (ObjectDisposedException ex) - { - Ivy.traceError(Resources.IvyWatcher, Resources.WatcherSocketClosed + ex.Message); - } - catch (SocketException se) - { - Ivy.traceError(Resources.IvyWatcher, Resources.WatcherSocketClosed + se.Message); - } - catch (IOException ioe) - { - Ivy.traceError(Resources.IvyWatcher, Resources.WatcherIOException + ioe.Message); - } - Ivy.traceProtocol(Resources.IvyWatcher, "end of a watcher thread"); + try + { + bool running = true; + while (running) + { + int version; + int appPort; + string appId; + string appName; + IPEndPoint remoteEP; + + stream.receiveMsg(out remoteEP, out version, out appPort, out appId, out appName); + IPAddress remotehost = remoteEP.Address; + + Ivy.traceProtocol(Resources.IvyWatcher, Resources.WatcherReceive + Dns.GetHostEntry(remotehost).HostName + ":" + remoteEP.Port); + + //TODO if ( !isInDomain( remotehost ) ) continue; + + if (version != stream.ProtocolVersion) + { + Ivy.traceError(Resources.IvyWatcher, Resources.BadVersion + version + " expected " + stream.ProtocolVersion); + continue; + } + + /* check if we received our own message. SHOULD ALSO TEST THE HOST */ + if (appId == bus.AppId) + continue; + if ((appPort == bus.applicationPort) && (remotehost.Equals(bus.applicationHost))) + continue; + + Ivy.traceProtocol(Resources.IvyWatcher, "reponse au Broadcast de " + Dns.GetHostEntry(remotehost).HostName + ":" + remoteEP.Port + " port " + appPort + + " version " + version + + " id " + appId + + " name " + appName); + + try + { + Socket socket = new Socket(ipv6 ? AddressFamily.InterNetworkV6 : AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); + IPEndPoint hostEndPoint = new IPEndPoint(remoteEP.Address, appPort); + socket.Blocking = true; + socket.Connect(hostEndPoint); + IvyClient client = new IvyClient(this.bus, socket, appName, appPort); + client.SendBindings(); + } + catch (SocketException e) + { + Ivy.traceError(Resources.IvyWatcher, Resources.WatcherConnectError + remotehost + " port " + appPort + " \n" + e.Message); + } + + } // while + } + catch (ObjectDisposedException ex) + { + Ivy.traceError(Resources.IvyWatcher, Resources.WatcherSocketClosed + ex.Message); + } + catch (SocketException se) + { + Ivy.traceError(Resources.IvyWatcher, Resources.WatcherSocketClosed + se.Message); + } + catch (IOException ioe) + { + Ivy.traceError(Resources.IvyWatcher, Resources.WatcherIOException + ioe.Message); + } + Ivy.traceProtocol(Resources.IvyWatcher, "end of a watcher thread"); } /// stops the thread waiting on the broadcast socket /// internal virtual void stop() { - lock (stream) + lock (stream) { - Ivy.traceProtocol(Resources.IvyWatcher, "begining stopping an IvyWatcher"); + Ivy.traceProtocol(Resources.IvyWatcher, "begining stopping an IvyWatcher"); stream.Close(); if (listenThread != null) { - // Wait for Thread to end. - bool term = listenThread.Join(10000); - if (!term && (listenThread != null)) listenThread.Abort(); + // Wait for Thread to end. + bool term = listenThread.Join(10000); + if (!term && (listenThread != null)) listenThread.Abort(); listenThread = null; } // it might not even have been created - Ivy.traceProtocol(Resources.IvyWatcher, "ending stopping an IvyWatcher"); + Ivy.traceProtocol(Resources.IvyWatcher, "ending stopping an IvyWatcher"); } } /// @@ -178,39 +187,39 @@ namespace IvyBus /// internal virtual void start() { - lock (stream) + lock (stream) { listenThread.Start(); - IPEndPoint EPhost = new IPEndPoint(group, port); - stream.sendMsg(EPhost, bus.applicationPort, bus.AppId, bus.AppName);// notifies our arrival on each domain: protocol version + port + IPEndPoint EPhost = new IPEndPoint(group, port); + stream.sendMsg(EPhost, bus.applicationPort, bus.AppId, bus.AppName);// notifies our arrival on each domain: protocol version + port } } - - - #region IDisposable Membres - - public void Dispose() - { - Dispose(true); - GC.SuppressFinalize(this); - } - - protected virtual void Dispose(bool disposing) - { - if (disposing) - { - // Free other state (managed objects). - if (stream != null) - { - stream.Close(); - stream = null; - } - } - // Free your own state (unmanaged objects). - // Set large fields to null. - - } - - #endregion - } + // Not needed for pure managed object ??!!! + + //#region IDisposable Membres + + //public void Dispose() + //{ + // Dispose(true); + // GC.SuppressFinalize(this); + //} + + //protected virtual void Dispose(bool disposing) + //{ + // if (disposing) + // { + // // Free other state (managed objects). + // if (stream != null) + // { + // stream.Close(); + // stream = null; + // } + // } + // // Free your own state (unmanaged objects). + // // Set large fields to null. + + //} + + //#endregion + } } \ No newline at end of file -- cgit v1.1