summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorfcolin2010-10-18 15:42:04 +0000
committerfcolin2010-10-18 15:42:04 +0000
commit5e310bef48ed719d15d88aafb9b92e674cb42b96 (patch)
tree76bbe7ba4fe2ec03576e6989eb2287cf03d2b5c8
parent657ff69295b138cf498968ac20653215c5d86252 (diff)
downloadivy-csharp-5e310bef48ed719d15d88aafb9b92e674cb42b96.zip
ivy-csharp-5e310bef48ed719d15d88aafb9b92e674cb42b96.tar.gz
ivy-csharp-5e310bef48ed719d15d88aafb9b92e674cb42b96.tar.bz2
ivy-csharp-5e310bef48ed719d15d88aafb9b92e674cb42b96.tar.xz
utilisation de socket IPV6 si le domain contient un multicast IPV6 genre FF02::1
-rw-r--r--Ivy/Ivy.cs2568
-rw-r--r--Ivy/IvyApplicationBinding.cs4
-rw-r--r--Ivy/IvyClient.cs767
-rw-r--r--Ivy/IvyUDPStream.cs2
-rw-r--r--Ivy/IvyWatcher.cs261
-rw-r--r--Ivy/app.config38
-rw-r--r--IvyControl/IvyControl.cs13
-rw-r--r--IvyControl/IvyDomain.Designer.cs17
-rw-r--r--IvyControl/IvyDomain.cs2
-rw-r--r--IvyControl/IvyDomain.resx3
-rw-r--r--IvyDaemon/IvyDaemon.cs6
-rw-r--r--IvyProbe/IvyProbe.Designer.cs16
-rw-r--r--IvyProbe/IvyProbe.cs11
-rw-r--r--IvyProbe/Properties/Settings.Designer.cs2
-rw-r--r--IvyProbe/Properties/Settings.settings2
-rw-r--r--IvyProbe/app.config2
16 files changed, 1905 insertions, 1809 deletions
diff --git a/Ivy/Ivy.cs b/Ivy/Ivy.cs
index 922bb27..9b0674f 100644
--- a/Ivy/Ivy.cs
+++ b/Ivy/Ivy.cs
@@ -7,1333 +7,1393 @@
[assembly: System.CLSCompliant(true)]
namespace IvyBus
{
- using System;
- using System.IO;
- using System.Collections;
- using System.Collections.Specialized;
- using System.Collections.Generic;
- using System.Net;
- using System.Net.Sockets;
- using System.Threading;
- using System.Configuration;
- using System.Globalization;
- using System.Text.RegularExpressions;
- using System.Text;
- using System.Reflection;
- using System.Diagnostics;
- using System.Collections.ObjectModel;
- using IvyBus.Properties;
-
- /// <summary> The Main bus Class
- /// </summary>
- ///
- public class Ivy
- {
- /* Event */
- /// <summary>
- /// raise when an new IvyClient is connected
- /// </summary>
- public event EventHandler<IvyEventArgs> ClientConnected;
- /// <summary>
- /// raise when an new IvyClient is disconnected
- /// </summary>
- public event EventHandler<IvyEventArgs> ClientDisconnected;
- /// <summary>
- /// raise when a direct message is received
- /// </summary>
- public event EventHandler<IvyEventArgs> DirectMessageReceived;
- /// <summary>
- /// raise when some IvyClient ask me to die
- /// </summary>
- public event EventHandler<IvyDieEventArgs> DieReceived;
- /// <summary>
- /// raise when an IvyClient register a binding
- /// </summary>
- public event EventHandler<IvyEventArgs> BindingAdd;
- /// <summary>
- /// raise when an IvyClient unregister a binding
- /// </summary>
- public event EventHandler<IvyEventArgs> BindingRemove;
- /// <summary>
- /// raise when an IvyClient binding is filteredout
- /// </summary>
- public event EventHandler<IvyEventArgs> BindingFilter;
- /// <summary>
- /// raise when an IvyClient changer a binding
- /// </summary>
- public event EventHandler<IvyEventArgs> BindingChange;
- /// <summary>
- /// raise when an error message is received
- /// </summary>
- public event EventHandler<IvyEventArgs> ErrorMessage;
-
- /// <summary>
- /// Flag for displaying internal debug message of the protocol intrinsics
- /// </summary>
- public static bool DebugProtocol
- {
- get
- {
- return debugProtocol;
- }
- set
- {
- debugProtocol = value;
- }
-
- }
- /// <summary>
- /// Language for the Ivy SendMsg formating default en-US
- /// ie: send point on float value sent
- /// </summary>
- public CultureInfo Culture
- {
- get
- {
- return culture;
- }
- set
- {
- culture = value;
- }
+ using System;
+ using System.IO;
+ using System.Collections;
+ using System.Collections.Specialized;
+ using System.Collections.Generic;
+ using System.Net;
+ using System.Net.Sockets;
+ using System.Threading;
+ using System.Configuration;
+ using System.Globalization;
+ using System.Text.RegularExpressions;
+ using System.Text;
+ using System.Reflection;
+ using System.Diagnostics;
+ using System.Collections.ObjectModel;
+ using IvyBus.Properties;
+
+ /// <summary> The Main bus Class
+ /// </summary>
+ ///
+ public class Ivy
+ {
+ /* Event */
+ /// <summary>
+ /// raise when an new IvyClient is connected
+ /// </summary>
+ public event EventHandler<IvyEventArgs> ClientConnected;
+ /// <summary>
+ /// raise when an new IvyClient is disconnected
+ /// </summary>
+ public event EventHandler<IvyEventArgs> ClientDisconnected;
+ /// <summary>
+ /// raise when a direct message is received
+ /// </summary>
+ public event EventHandler<IvyEventArgs> DirectMessageReceived;
+ /// <summary>
+ /// raise when some IvyClient ask me to die
+ /// </summary>
+ public event EventHandler<IvyDieEventArgs> DieReceived;
+ /// <summary>
+ /// raise when an IvyClient register a binding
+ /// </summary>
+ public event EventHandler<IvyEventArgs> BindingAdd;
+ /// <summary>
+ /// raise when an IvyClient unregister a binding
+ /// </summary>
+ public event EventHandler<IvyEventArgs> BindingRemove;
+ /// <summary>
+ /// raise when an IvyClient binding is filteredout
+ /// </summary>
+ public event EventHandler<IvyEventArgs> BindingFilter;
+ /// <summary>
+ /// raise when an IvyClient changer a binding
+ /// </summary>
+ public event EventHandler<IvyEventArgs> BindingChange;
+ /// <summary>
+ /// raise when an error message is received
+ /// </summary>
+ public event EventHandler<IvyEventArgs> ErrorMessage;
+
+ /// <summary>
+ /// Flag for displaying internal debug message of the protocol intrinsics
+ /// </summary>
+ public static bool DebugProtocol
+ {
+ get
+ {
+ return debugProtocol;
+ }
+ set
+ {
+ debugProtocol = value;
+ }
- }
+ }
+ /// <summary>
+ /// Language for the Ivy SendMsg formating default en-US
+ /// ie: send point on float value sent
+ /// </summary>
+ public CultureInfo Culture
+ {
+ get
+ {
+ return culture;
+ }
+ set
+ {
+ culture = value;
+ }
- /// <summary>IvyClients accesses the list of the connected clients</summary>
+ }
- public ReadOnlyCollection<IvyClient> IvyClients
- {
- get
- {
- return new ReadOnlyCollection<IvyClient>(clients);
- }
+ /// <summary>IvyClients accesses the list of the connected clients</summary>
- }
-
- /// <summary>AppName the application name</summary>
+ public ReadOnlyCollection<IvyClient> IvyClients
+ {
+ get
+ {
+ return new ReadOnlyCollection<IvyClient>(clients);
+ }
- public string AppName
- {
- set
- {
- appName = value;
- }
- get
- {
- return appName;
- }
+ }
+
+ /// <summary>AppName the application name</summary>
- }
- /// <summary>
- /// AppId the Application Unique ID
- /// </summary>
+ public string AppName
+ {
+ set
+ {
+ appName = value;
+ }
+ get
+ {
+ return appName;
+ }
- public string AppId
- {
- get
- {
- return applicationUniqueId;
- }
+ }
+ /// <summary>
+ /// AppId the Application Unique ID
+ /// </summary>
- }
-
- /// <summary>
- /// the Ivy Protocol version
- /// </summary>
- public int ProtocolVersion
- {
- get
- {
- return protocolVersion;
- }
+ public string AppId
+ {
+ get
+ {
+ return applicationUniqueId;
+ }
- }
+ }
+
+ /// <summary>
+ /// the Ivy Protocol version
+ /// </summary>
+ public int ProtocolVersion
+ {
+ get
+ {
+ return protocolVersion;
+ }
- /// <summary>
- /// IsRunning is the bus Started and connected ?
- /// </summary>
- public bool IsRunning
- {
- get
- {
- return !stopped;
- }
+ }
+ /// <summary>
+ /// IsSynchronous is the bus Synchronous of the main thread ( ie callback running in the main thread) ?
+ /// </summary>
+ private bool synchronous = true;
+ public bool Synchronous
+ {
+ set
+ {
+ synchronous = value && syncContext != null;
+ }
+ get
+ {
+ return synchronous;
+ }
- }
- ///<summary>SentMessageClasses the first word token of sent messages
- ///<remarks> optimise the parsing process when sending messages </remarks>
- ///</summary>
+ }
- public Collection<string> SentMessageFilter
- {
- get
- {
- return sent_messageFilter;
- }
- }
- /// <summary>ReadyMessage message send when Application receive all the regexp at the connection of the client</summary>
+ /// <summary>
+ /// IsRunning is the bus Started and connected ?
+ /// </summary>
+ public bool IsRunning
+ {
+ get
+ {
+ return !stopped;
+ }
- public string ReadyMessage
- {
- get { return ready_message; }
- set { ready_message = value; }
- }
+ }
+ ///<summary>SentMessageClasses the first word token of sent messages
+ ///<remarks> optimise the parsing process when sending messages </remarks>
+ ///</summary>
- internal class MyTcpListener : TcpListener
- {
- public MyTcpListener(IPAddress address, int port)
- : base(address, port)
- {
- }
- public bool IsActive()
- {
- return this.Active;
- }
- }
- /// the name of the application on the bus
- internal string appName;
- /// the port for the UDP rendez vous, if none is supplied
- internal const ushort DefaultPort = 2010;
- /// the domain for the UDP rendez vous
- private static readonly string DefaultDomain = "127.0.0.1:" + DefaultPort;
- internal int protocolVersion = 3;
- private static bool debugProtocol; // false by default runtime
- private static int serial = -1; /* an unique ID for each regexp */ // -1 to start numbering at 0
- private MyTcpListener app;
- private List<IvyWatcher> watchers;
- private Thread serverThread; // to ensure quick communication of the end
- private AutoResetEvent tcplistener_running;
-
- /// <summary>
- /// the Ivy Assembly version
- /// </summary>
- static public Version Version
- {
- get { return Assembly.GetExecutingAssembly().GetName().Version; }
- }
- // Class representing Ivy Binding receive from client
- internal class IvyClientBinding
- {
- internal IvyBindingBase binding;
- internal Dictionary<IvyClient, List<int>> client_bindind_ids;
- }
- // The Application bindings
- internal Dictionary<int, IvyApplicationBinding> bindings;
- // the clients bindings
- private Dictionary<string, IvyClientBinding > client_bindings;
- private List<IvyClient> clients;
- private Collection<string> sent_messageFilter;
- private bool stopped = true;
- internal int applicationPort; /* Application port number */
- internal IPAddress applicationHost; /* Application host number */
- internal string applicationUniqueId; /* identifier Application unique timestamp-ipaddress-port */
- private string ready_message;
- private CultureInfo culture = new CultureInfo("en-us");
- internal static Encoding ivyEncoding = Encoding.GetEncoding("iso-8859-15"); // ASCII 8 bits iso-8859-2
+ public Collection<string> SentMessageFilter
+ {
+ get
+ {
+ return sent_messageFilter;
+ }
+ }
+ /// <summary>ReadyMessage message send when Application receive all the regexp at the connection of the client</summary>
+
+ public string ReadyMessage
+ {
+ get { return ready_message; }
+ set { ready_message = value; }
+ }
+
+ internal class MyTcpListener : TcpListener
+ {
+ public MyTcpListener(IPAddress address, int port)
+ : base(address, port)
+ {
+ }
+ public bool IsActive()
+ {
+ return this.Active;
+ }
+ }
+ /// the name of the application on the bus
+ internal string appName;
+ /// the port for the UDP rendez vous, if none is supplied
+ internal const ushort DefaultPort = 2010;
+ /// the domain for the UDP rendez vous
+ private static readonly string DefaultDomain = "127.0.0.1:" + DefaultPort;
+ internal int protocolVersion = 3;
+ private static bool debugProtocol; // false by default runtime
+ private static int serial = -1; /* an unique ID for each regexp */ // -1 to start numbering at 0
+ private MyTcpListener app;
+ private List<IvyWatcher> watchers;
+ private Thread serverThread; // to ensure quick communication of the end
+ private AutoResetEvent tcplistener_running;
+ private bool ipv6;
+
+ /// <summary>
+ /// the Ivy IP version to use
+ /// </summary>
+ public bool IpV6
+ {
+ get { return ipv6; }
+ }
+
+ /// <summary>
+ /// the Ivy Assembly version
+ /// </summary>
+ static public Version Version
+ {
+ get { return Assembly.GetExecutingAssembly().GetName().Version; }
+ }
+ // Class representing Ivy Binding receive from client
+ internal class IvyClientBinding
+ {
+ internal IvyBindingBase binding;
+ internal Dictionary<IvyClient, List<int>> client_bindind_ids;
+ }
+ // The Application bindings
+ internal Dictionary<int, IvyApplicationBinding> bindings;
+ // the clients bindings
+ private Dictionary<string, IvyClientBinding > client_bindings;
+ private List<IvyClient> clients;
+ private Collection<string> sent_messageFilter;
+ private bool stopped = true;
+ internal int applicationPort; /* Application port number */
+ internal IPAddress applicationHost; /* Application host number */
+ internal string applicationUniqueId; /* identifier Application unique timestamp-ipaddress-port */
+ private string ready_message;
+ private CultureInfo culture = new CultureInfo("en-us");
+ internal static Encoding ivyEncoding = Encoding.GetEncoding("iso-8859-15"); // ASCII 8 bits iso-8859-2
- // for synchronous event
+ // for synchronous event
#if (PocketPC)
- private System.Windows.Forms.ContainerControl parentControl;
+ private System.Windows.Forms.ContainerControl parentControl;
#else
- private readonly SynchronizationContext syncContext;
+ private readonly SynchronizationContext syncContext;
#endif
- /// <summary>
- /// Initializes a new instance of the Ivy Bus.
- /// Readies the structures for the software bus connexion.
- /// </summary>
- public Ivy()
- {
- clients = new List<IvyClient>();
- bindings = new Dictionary<int, IvyApplicationBinding>();
- client_bindings = new Dictionary<string, IvyClientBinding>();
- sent_messageFilter = new Collection<string>();
+ /// <summary>
+ /// Initializes a new instance of the Ivy Bus.
+ /// Readies the structures for the software bus connexion.
+ /// </summary>
+ public Ivy()
+ {
+ this.ipv6 = false;
+ clients = new List<IvyClient>();
+ bindings = new Dictionary<int, IvyApplicationBinding>();
+ client_bindings = new Dictionary<string, IvyClientBinding>();
+ sent_messageFilter = new Collection<string>();
#if (!PocketPC)
- syncContext = SynchronizationContext.Current;
- debugProtocol = Properties.Settings.Default.IvyDebug;
- protocolVersion = Properties.Settings.Default.IvyProtocolVersion;
+ syncContext = SynchronizationContext.Current;
+ debugProtocol = Properties.Settings.Default.IvyDebug;
+ protocolVersion = Properties.Settings.Default.IvyProtocolVersion;
#endif
- // get binding from Attribute IvyBinding
- //TODO Autobinding attribute
+ // get binding from Attribute IvyBinding
+ //TODO Autobinding attribute
#if (PocketPC)
- if (parentControl != null)
- BindAttibute(parentControl);
+ if (parentControl != null)
+ BindAttibute(parentControl);
#endif
- Assembly assembly = Assembly.GetCallingAssembly();
- if ( assembly != this.GetType().Assembly )
- BindAttribute(assembly);
- }
-
- /// <summary>
- /// Readies the structures for the software bus connexion.
- /// </summary>
- /// <example> This sample shows how to start working with Ivy.
- /// <code>
- /// Ivy bus = new Ivy("Dummy agent","ready");
- /// bus.bindMsg("(.*)",myMessageListener);
- /// bus.start(null);
- /// </code>
- /// How to send & receive:
- /// the Ivy agent A performs <c>b.bindMsg("^Hello (*)",cb);</c>
- /// the Ivy agent B performs <c>b2.sendMsg("Hello world");</c>
- /// a thread in A will run the callback cb with its second argument set
- /// to a array of string, with one single element, "world"
- /// </example>
- /// <remarks>
- /// the real work begin in the start() method
- /// </remarks>
- /// <seealso cref=" Ivy.start"/>
- /// <param name='name'>The name of your Ivy agent on the software bus
- /// </param>
- /// <param name='message'>The hellow message you will send once ready
- /// </param>
- public Ivy(string name, string readyMessage)
- : this()
- {
- appName = name;
- this.ready_message = readyMessage;
- // get binding from Attribute IvyBinding
- //TODO Autobinding attribute
- Assembly assembly = Assembly.GetCallingAssembly();
- if (assembly != this.GetType().Assembly)
- BindAttribute(assembly);
- }
-
- internal void AddBinding(int id, IvyClient clnt, IvyBindingBase bindexp)
- {
- bool change = false;
- IvyClientBinding clientbind;
- lock (client_bindings)
- {
- if (client_bindings.ContainsKey(bindexp.Expression))
- {
- // check if id exits to remove it
-
- clientbind = client_bindings[bindexp.Expression];
-
- foreach (IvyClientBinding clbind in client_bindings.Values)
- {
- lock (clbind.client_bindind_ids)
- {
- if (clbind.client_bindind_ids.ContainsKey(clnt))
- {
- if (clbind.client_bindind_ids[clnt].Contains(id))
- {
- // remove from old
- clbind.client_bindind_ids[clnt].Remove(id);
- // add to new later
- change = true; //mark to call right handler
- break;
- }
- }
- }
-
- }
-
- }
- else
- {
- clientbind = new IvyClientBinding();
- clientbind.binding = bindexp;
- clientbind.client_bindind_ids = new Dictionary<IvyClient, List<int>>();
- clientbind.client_bindind_ids[clnt] = new List<int>();
- client_bindings[bindexp.Expression] = clientbind;
-
- }
- }
-
- lock (clientbind.client_bindind_ids)
- {
- if (!clientbind.client_bindind_ids.ContainsKey(clnt))
- {
- clientbind.client_bindind_ids[clnt] = new List<int>();
- }
- clientbind.client_bindind_ids[clnt].Add(id);
- }
- if (change)
- {
- OnClientChangeBinding(new IvyEventArgs(clnt, id, bindexp.Expression));
- }
- else
- {
- OnClientAddBinding(new IvyEventArgs(clnt, id, bindexp.Expression));
- }
- }
- internal void DelBinding(int id, IvyClient clnt)
- {
- IvyClientBinding clientbind = null;
- lock (client_bindings)
- {
- foreach (IvyClientBinding clbind in client_bindings.Values)
- {
- lock (clbind.client_bindind_ids)
- {
- if (clbind.client_bindind_ids.ContainsKey(clnt))
- {
- clbind.client_bindind_ids[clnt].Remove(id);
- clientbind = clbind;
- break;
- }
- }
- }
- if (clientbind != null)
- {
- lock (clientbind.client_bindind_ids)
- {
- if (clientbind.client_bindind_ids.Count == 0)
- {
- client_bindings.Remove(clientbind.binding.Expression);
- }
- }
- }
- }
- if (clientbind != null )
- OnClientRemoveBinding(new IvyEventArgs(clnt, id, clientbind.binding.Expression));
-
- }
- /// <summary>
- /// Automatic binding on static method of a Type
- /// </summary>
- /// <param name="type"></param>
- public void BindAttribute(Type type)
- {
- if (type == null) return;
- //Get instance of the IvyBindingAttribute.
- foreach (MethodInfo m in type.GetMethods(BindingFlags.Static | BindingFlags.NonPublic))
- {
- foreach (IvyBindingAttribute attr in Attribute.GetCustomAttributes(m, typeof(IvyBindingAttribute)))
- {
- //TODO check paramater type MessageHandler
- Debug.WriteLine("IvyBinding '" + attr.GetFormattedExpression(null) + "' to Method " + m.Name);
- EventHandler<IvyMessageEventArgs> handler;
+ Assembly assembly = Assembly.GetCallingAssembly();
+ if ( assembly != this.GetType().Assembly )
+ BindAttribute(assembly);
+ }
+
+ /// <summary>
+ /// Readies the structures for the software bus connexion.
+ /// </summary>
+ /// <example> This sample shows how to start working with Ivy.
+ /// <code>
+ /// Ivy bus = new Ivy("Dummy agent","ready");
+ /// bus.bindMsg("(.*)",myMessageListener);
+ /// bus.start(null);
+ /// </code>
+ /// How to send & receive:
+ /// the Ivy agent A performs <c>b.bindMsg("^Hello (*)",cb);</c>
+ /// the Ivy agent B performs <c>b2.sendMsg("Hello world");</c>
+ /// a thread in A will run the callback cb with its second argument set
+ /// to a array of string, with one single element, "world"
+ /// </example>
+ /// <remarks>
+ /// the real work begin in the start() method
+ /// </remarks>
+ /// <seealso cref=" Ivy.start"/>
+ /// <param name='name'>The name of your Ivy agent on the software bus
+ /// </param>
+ /// <param name='message'>The hellow message you will send once ready
+ /// </param>
+ public Ivy(string name, string readyMessage)
+ : this()
+ {
+ appName = name;
+ this.ready_message = readyMessage;
+
+ // get binding from Attribute IvyBinding
+ //TODO Autobinding attribute
+ Assembly assembly = Assembly.GetCallingAssembly();
+ if (assembly != this.GetType().Assembly)
+ BindAttribute(assembly);
+ }
+
+
+ internal void AddBinding(int id, IvyClient clnt, IvyBindingBase bindexp)
+ {
+ bool change = false;
+ IvyClientBinding clientbind;
+ lock (client_bindings)
+ {
+ if (client_bindings.ContainsKey(bindexp.Expression))
+ {
+ // check if id exits to remove it
+
+ clientbind = client_bindings[bindexp.Expression];
+
+ foreach (IvyClientBinding clbind in client_bindings.Values)
+ {
+ lock (clbind.client_bindind_ids)
+ {
+ if (clbind.client_bindind_ids.ContainsKey(clnt))
+ {
+ if (clbind.client_bindind_ids[clnt].Contains(id))
+ {
+ // remove from old
+ clbind.client_bindind_ids[clnt].Remove(id);
+ // add to new later
+ change = true; //mark to call right handler
+ break;
+ }
+ }
+ }
+
+ }
+
+ }
+ else
+ {
+ clientbind = new IvyClientBinding();
+ clientbind.binding = bindexp;
+ clientbind.client_bindind_ids = new Dictionary<IvyClient, List<int>>();
+ clientbind.client_bindind_ids[clnt] = new List<int>();
+ client_bindings[bindexp.Expression] = clientbind;
+
+ }
+ }
+
+ lock (clientbind.client_bindind_ids)
+ {
+ if (!clientbind.client_bindind_ids.ContainsKey(clnt))
+ {
+ clientbind.client_bindind_ids[clnt] = new List<int>();
+ }
+ clientbind.client_bindind_ids[clnt].Add(id);
+ }
+ if (change)
+ {
+ OnClientChangeBinding(new IvyEventArgs(clnt, id, bindexp.Expression));
+ }
+ else
+ {
+ OnClientAddBinding(new IvyEventArgs(clnt, id, bindexp.Expression));
+ }
+ }
+ internal void DelBinding(int id, IvyClient clnt)
+ {
+ IvyClientBinding clientbind = null;
+ lock (client_bindings)
+ {
+ foreach (IvyClientBinding clbind in client_bindings.Values)
+ {
+ lock (clbind.client_bindind_ids)
+ {
+ if (clbind.client_bindind_ids.ContainsKey(clnt))
+ {
+ clbind.client_bindind_ids[clnt].Remove(id);
+ clientbind = clbind;
+ break;
+ }
+ }
+ }
+ if (clientbind != null)
+ {
+ lock (clientbind.client_bindind_ids)
+ {
+ if (clientbind.client_bindind_ids.Count == 0)
+ {
+ client_bindings.Remove(clientbind.binding.Expression);
+ }
+ }
+ }
+ }
+ if (clientbind != null )
+ OnClientRemoveBinding(new IvyEventArgs(clnt, id, clientbind.binding.Expression));
+
+ }
+ /// <summary>
+ /// Automatic binding on static method of a Type
+ /// </summary>
+ /// <param name="type"></param>
+ public void BindAttribute(Type type)
+ {
+ if (type == null) return;
+ //Get instance of the IvyBindingAttribute.
+ foreach (MethodInfo m in type.GetMethods(BindingFlags.Static | BindingFlags.NonPublic))
+ {
+ foreach (IvyBindingAttribute attr in Attribute.GetCustomAttributes(m, typeof(IvyBindingAttribute)))
+ {
+ //TODO check paramater type MessageHandler
+ Debug.WriteLine("IvyBinding '" + attr.GetFormattedExpression(null) + "' to Method " + m.Name);
+ EventHandler<IvyMessageEventArgs> handler;
#if (PocketPC)
- //Createdelegate mydlg = new Createdelegate(m, null, EventArgs.Empty);
- //bindMsg(attr.GetExpression(null), mydlg);
- handler = null;
+ //Createdelegate mydlg = new Createdelegate(m, null, EventArgs.Empty);
+ //bindMsg(attr.GetExpression(null), mydlg);
+ handler = null;
#else
- handler = (EventHandler<IvyMessageEventArgs>)Delegate.CreateDelegate(typeof(EventHandler<IvyMessageEventArgs>), m);
+ handler = (EventHandler<IvyMessageEventArgs>)Delegate.CreateDelegate(typeof(EventHandler<IvyMessageEventArgs>), m);
#endif
- BindMsg(attr.GetFormattedExpression(null), handler);
- }
- }
- }
-
-
- /// <summary>
- /// Autobinding on instance method
- /// </summary>
- /// <param name="target"></param>
- public void BindAttribute(object target)
- {
- if (target == null) return;
- Type type = target.GetType();
- //Get instance of the IvyBindingAttribute.
- foreach (MethodInfo m in type.GetMethods(BindingFlags.Instance | BindingFlags.NonPublic))
- {
- foreach (IvyBindingAttribute attr in Attribute.GetCustomAttributes(m, typeof(IvyBindingAttribute)))
- {
- //TODO check paramater type MessageHandler
- Ivy.traceProtocol(Resources.Ivy, "BindAttibute " + attr.GetFormattedExpression(target) + "' to Method " + m.Name);
- EventHandler<IvyMessageEventArgs> handler;
+ BindMsg(attr.GetFormattedExpression(null), handler);
+ }
+ }
+ }
+
+
+ /// <summary>
+ /// Autobinding on instance method
+ /// </summary>
+ /// <param name="target"></param>
+ public void BindAttribute(object target)
+ {
+ if (target == null) return;
+ Type type = target.GetType();
+ //Get instance of the IvyBindingAttribute.
+ foreach (MethodInfo m in type.GetMethods(BindingFlags.Instance | BindingFlags.NonPublic))
+ {
+ foreach (IvyBindingAttribute attr in Attribute.GetCustomAttributes(m, typeof(IvyBindingAttribute)))
+ {
+ //TODO check paramater type MessageHandler
+ Ivy.traceProtocol(Resources.Ivy, "BindAttibute " + attr.GetFormattedExpression(target) + "' to Method " + m.Name);
+ EventHandler<IvyMessageEventArgs> handler;
#if (PocketPC)
- handler = null; // TODO
+ handler = null; // TODO
#else
- handler = (EventHandler<IvyMessageEventArgs>)Delegate.CreateDelegate(typeof(EventHandler<IvyMessageEventArgs>), target, m);
+ handler = (EventHandler<IvyMessageEventArgs>)Delegate.CreateDelegate(typeof(EventHandler<IvyMessageEventArgs>), target, m);
#endif
- BindMsg(attr.GetFormattedExpression(target), handler);
- }
- }
+ BindMsg(attr.GetFormattedExpression(target), handler);
+ }
+ }
- }
- // Autobinding on IvyBindingAttribute method
- /// <summary>
- /// Automatic binding of IvyBindAttribute in an assembly
- /// </summary>
- /// <param name="target"></param>
- public void BindAttribute(Assembly target)
- {
- if (target != null)
- {
- foreach (Type typ in target.GetTypes())
- {
- BindAttribute(typ);
- }
- }
- }
- /// <summary>
- /// connects the Ivy bus to a domain or list of domains.
- /// </summary>
- /// <param name="domainbus">a domain of the form 10.0.0:1234, it is similar to the
- /// netmask without the trailing .255. This will determine the meeting point
- /// of the different applications. Right now, this is done with an UDP
- /// broadcast. Beware of routing problems ! You can also use a comma
- /// separated list of domains.</param>
- /// <remarks>
- /// One thread (IvyWatcher) for each traffic rendezvous (either UDP broadcast or TCP Multicast).
- /// One thread (serverThread/Ivy) to accept incoming connexions on server socket.
- /// a thread for each IvyClient when the connexion has been done.
- /// </remarks>
- public void Start(string domainBus)
- {
- domainBus = GetDomain(domainBus);
- try
- {
- long seed = DateTime.Now.Ticks / TimeSpan.TicksPerMillisecond;
- Random rand = new Random( (int)seed );
-
- app = new MyTcpListener(IPAddress.Any, 0);
- app.Start(); // should be started before getting port
- applicationHost = LocalIP;
- applicationPort = ((IPEndPoint)app.LocalEndpoint).Port;
- applicationUniqueId = string.Format(culture,"{0}:{1}:{2}",
- rand.Next(),
- seed,
- //applicationHost.ToString().Replace(".", ""),
- applicationPort);
+ }
+ // Autobinding on IvyBindingAttribute method
+ /// <summary>
+ /// Automatic binding of IvyBindAttribute in an assembly
+ /// </summary>
+ /// <param name="target"></param>
+ public void BindAttribute(Assembly target)
+ {
+ if (target != null)
+ {
+ foreach (Type typ in target.GetTypes())
+ {
+ BindAttribute(typ);
+ }
+ }
+ }
+ /// <summary>
+ /// connects the Ivy bus to a domain or list of domains.
+ /// </summary>
+ /// <param name="domainbus">a domain of the form 10.0.0:1234, it is similar to the
+ /// netmask without the trailing .255. This will determine the meeting point
+ /// of the different applications. Right now, this is done with an UDP
+ /// broadcast. Beware of routing problems ! You can also use a comma
+ /// separated list of domains.</param>
+ /// <remarks>
+ /// One thread (IvyWatcher) for each traffic rendezvous (either UDP broadcast or TCP Multicast).
+ /// One thread (serverThread/Ivy) to accept incoming connexions on server socket.
+ /// a thread for each IvyClient when the connexion has been done.
+ /// </remarks>
+ public void Start(string domainBus)
+ {
+ domainBus = GetDomain(domainBus);
+ // check for IPV6 mode
+ Domain[] d = parseDomains(domainBus);
+ IPAddress group = IPAddress.Parse(d[0].Domainaddr);
+ ipv6 = group.IsIPv6Multicast;
+
+ try
+ {
+ long seed = DateTime.Now.Ticks / TimeSpan.TicksPerMillisecond;
+ Random rand = new Random( (int)seed );
+
+ app = new MyTcpListener(ipv6 ? IPAddress.IPv6Any :IPAddress.Any, 0);
+ app.Start(); // should be started before getting port
+ applicationHost = LocalIP;
+ applicationPort = ((IPEndPoint)app.LocalEndpoint).Port;
+ applicationUniqueId = string.Format(culture,"{0}:{1}:{2}",
+ rand.Next(),
+ seed,
+ //applicationHost.ToString().Replace(".", ""),
+ applicationPort);
- }
- catch (IOException e)
- {
- throw new IvyException("can't open TCP service socket " + e);
- }
- Ivy.traceProtocol("BindAttibute", "Ivy protocol: " + ProtocolVersion + " TCP service open on port " + applicationPort);
- watchers = new List<IvyWatcher>();
+ }
+ catch (IOException e)
+ {
+ throw new IvyException("can't open TCP service socket " + e);
+ }
+ Ivy.traceProtocol("BindAttibute", "Ivy protocol: " + ProtocolVersion + " TCP service open on port " + applicationPort);
+ watchers = new List<IvyWatcher>();
- Domain[] d = parseDomains(domainBus);
- // readies the rendezvous : an IvyWatcher (thread) per domain bus
- for (int index = 0; index < d.Length; index++)
- {
- IvyWatcher watcher = new IvyWatcher(this, d[index].Domainaddr, d[index].Port);
- watchers.Add(watcher);
- }
- serverThread = new Thread(new ThreadStart(this.TcpListener));
- serverThread.Name = "Ivy Tcp Server Thread";
- stopped = false;
- tcplistener_running = new AutoResetEvent(false);
- serverThread.Start();
+ // readies the rendezvous : an IvyWatcher (thread) per domain bus
+ for (int index = 0; index < d.Length; index++)
+ {
+ IvyWatcher watcher = new IvyWatcher(this, d[index].Domainaddr, d[index].Port, ipv6 );
+ watchers.Add(watcher);
+ }
+ serverThread = new Thread(new ThreadStart(this.TcpListener));
+ serverThread.Name = "Ivy Tcp Server Thread";
+ stopped = false;
+ tcplistener_running = new AutoResetEvent(false);
+ serverThread.Start();
// Wait for readyness
- tcplistener_running.WaitOne();
+ tcplistener_running.WaitOne();
- // sends the broadcasts and listen to incoming connexions
- for (int i = 0; i < watchers.Count; i++)
- {
- watchers[i].start();
- }
- }
- internal void SortClients()
- {
- lock (clients)
- {
- //clients.Sort(new IvyClient.IvyClientPriority());
- clients.Sort();
- }
- }
-
-
- internal static Domain[] parseDomains(string domainbus)
- {
- string[] st = domainbus.Split(',');
- Domain[] d = new Domain[st.Length];
- for (int i = 0; i < st.Length; i++)
- {
- d[i] = new Domain(st[i]);
- }
- return d;
- }
-
- /// <summary>
- /// disconnects from the Ivy bus
- /// </summary>
- public void Stop()
- {
- if (stopped)
- return;
- lock (app)
- {
- stopped = true;
- Ivy.traceProtocol(Resources.Ivy, "beginning stopping the bus");
- try
- {
- // stopping the serverThread
- if (serverThread != null)
- {
- app.Stop();
- // Wait for Thread to end.
- bool term = serverThread.Join(10000);
- if (!term && (serverThread != null)) serverThread.Abort();
- serverThread = null;
- }
- // The serverThread might be stopped even before having been created
- if (app != null)
- app.Stop();
- // stopping the IvyWatchers
- if (watchers != null)
- for (int i = 0; i < watchers.Count; i++)
- {
- ((IvyWatcher)watchers[i]).stop();
- }
- // stopping the remaining IvyClients
- // copy the values in temporary variable to eliminate Thread modifying collection
- if (clients.Count != 0)
- {
- IvyClient[] copyClient;
- lock (clients)
- {
- copyClient = new IvyClient[clients.Count];
- clients.CopyTo(copyClient);
- }
- foreach (IvyClient client in copyClient)
- {
- client.close(true); // will notify the reading thread
- //removeClient(client); already donne in the thread
- }
- }
- }
- catch (IOException e)
- {
- Ivy.traceError(Resources.Ivy, "IOexception Stop " + e.Message);
- }
- Ivy.traceProtocol(Resources.Ivy, "the bus should have stopped so far");
- }
- }
- /// <summary>
- /// join the main thread of Ivy ( ie wait until stopped )
- /// </summary>
- /// <remarks>
- /// Performs a join on the Principal Thread.
- /// </remarks>
- /// <param name='millisecondsTimeout'>Number of millisecondes to wait before the Thread Stop.</param>
- /// <returns>
- /// true if the thread stopped; false if it did not stop after the expiry of the period specified by the parameter millisecondsTimeout
- /// </returns>
- public bool Join(int millisecondsTimeout)
- {
- return serverThread.Join(millisecondsTimeout);
- }
- /// <summary>
- /// Block the calling Thread until Ivy Stop
- /// </summary>
- /// <remarks>
- /// Performs a join on the Principal Thread.
- /// </remarks>
- public void MainLoop()
- {
- this.Join(Timeout.Infinite);
- }
-
- /// <summary>
- /// Send a formated message to someone on the bus
- /// </summary>
- /// <remarks>
- /// Performs a pattern matching according to everyone's regexps, and sends
- /// the results to the relevant ivy agents.
- /// There is one thread for each client connected, we could also
- /// create another thread each time we send a message.
- /// </remarks>
- /// <param name='format'>A string message format to build the message</param>
- /// <param name='args'>args used in message format</param>
- /// <returns>
- /// the number of messages actually sent
- /// </returns>
- public int SendMsg(string format, params object[] args)
- {
- // send to everybody
- string msg = string.Format(culture, format, args);
- int count = 0;
- // hash message in V4 protocol only
- if (ProtocolVersion == 4)
- IvyBindingSimple.Prepare(msg);
- // an alternate implementation would one sender thread per client
- // instead of one for all the clients. It might be a performance issue
- // Tentative of using BeginInvoke EndInvoke is slower
- lock (client_bindings)
- {
- foreach (IvyClientBinding clbind in client_bindings.Values)
- {
- string[] matches = clbind.binding.Match(msg);
- if (matches != null)
- {
- lock (clbind.client_bindind_ids)
- {
-
- foreach (KeyValuePair<IvyClient, List<int>> assoc in clbind.client_bindind_ids)
- {
- foreach (ushort id in assoc.Value)
- {
- count += assoc.Key.sendMsg(id, matches);
- }
-
- }
-
- }
- }
-
- }
-
- }
-
- return count;
- }
-
- internal int SendMsgToClient(IvyClient clnt, string format, params object[] args)
- {
- string msg = string.Format(culture, format, args);
- int count = 0;
- // hash message in V4 protocol only
- if (ProtocolVersion == 4)
- IvyBindingSimple.Prepare(msg);
- // an alternate implementation would one sender thread per client
- // instead of one for all the clients. It might be a performance issue
- lock (client_bindings)
- {
-
- foreach (IvyClientBinding clbind in client_bindings.Values)
- {
- string[] matches = clbind.binding.Match(msg);
- if (matches != null)
- {
- lock (clbind.client_bindind_ids)
- {
- if (clbind.client_bindind_ids.ContainsKey(clnt))
- {
- List<int> ids = clbind.client_bindind_ids[clnt];
- foreach (ushort id in ids)
- {
- count += clnt.sendMsg(id, matches);
- }
- }
- }
- }
- }
- }
-
-
- return count;
- }
- /// <summary>
- /// Make a binding to a message using regular expresssion
- /// </summary>
- /// <param name="newBinding"></param>
- /// <returns></returns>
- public int BindMsg(IvyApplicationBinding newBinding)
- {
- newBinding.Key = Interlocked.Increment(ref serial);
-
- lock (bindings) bindings.Add(newBinding.Key, newBinding);
- // notifies the other clients this new regexp
- lock (clients)
- {
- foreach (IvyClient c in clients)
- {
- c.stream.TokenAddBinding(newBinding.Binding, newBinding.Key, newBinding.FormattedExpression);
- }
- }
- return newBinding.Key;
- }
- /// <summary>
- /// Subscribes to a regular expression.
- /// </summary>
- /// <param name="regexp">a regular expression, groups are done with parenthesis</param>
- /// <param name="callback">any objects implementing the EventHandler<IvyMessageEventArgs> </param>
- /// <param name="args">The args.</param>
- /// <returns>the id of the regular expression</returns>
- /// <remarks>
- /// The callback will be executed with
- /// the saved parameters of the regexp as arguments when a message will sent
- /// by another agent. A program doesn't receive its own messages.
- /// the expression cant containt some dynamics argument replacement of the form %number[:objectFormat]%
- /// the string will be replaced by arg[number].ToString(objectFormat)
- /// </remarks>
- //
- public int BindMsg(string expression, EventHandler<IvyMessageEventArgs> callback, params object[] args)
- {
- // creates a new binding (regexp,callback)
- IvyApplicationBinding newbind;
- newbind = new IvyApplicationBinding(BindingType.RegularExpression, expression, args);
- newbind.Callback += callback;
- return BindMsg(newbind);
- }
-
- /// <summary>
- /// unsubscribes a regular expression
- /// </summary>
- /// <param name="id">the id of the regular expression, returned when it was bound</param>
- public void UnbindMsg(int id)
- {
- if (!bindings.ContainsKey(id))
- {
- throw new IvyException("client wants to remove an unexistant regexp " + id);
- }
- lock (clients)
- {
- foreach (IvyClient c in clients)
- {
- try
- {
- if ( c.stream != null )
- c.stream.TokenDelBinding(id);
- }
- catch (IOException)
- {
- // client closed ignore it
- }
- }
- }
- lock (bindings) bindings.Remove(id);
- }
- /// <summary>
- /// Change a binding already registred
- /// </summary>
- /// <param name="id"></param>
- /// <param name="expression"></param>
- /// <returns></returns>
- public int ChangeMsg(int id, string expression)
- {
- IvyApplicationBinding newbind;
- if (!bindings.ContainsKey(id))
- {
- throw new IvyException("client wants to change an unexistant regexp " + id);
- }
-
- // change binding (regexp,callback)
- lock (bindings)
- {
- newbind = bindings[id];
- newbind.Expression = expression;
- }
- // notifies the other clients this new regexp
- lock (clients)
- {
- foreach (IvyClient c in clients)
- {
- c.stream.TokenAddBinding(newbind.Binding, newbind.Key, newbind.FormattedExpression);
- }
- }
- return id;
- }
-
-
- /// <summary>
- /// unsubscribes a regular expression
- /// </summary>
- /// <param name="re">the string for the regular expression</param>
- /// <returns>
- /// a boolean, true if the regexp existed, false otherwise or
- /// whenever an exception occured during unbinding
- /// </returns>
- public bool UnbindMsg(string re)
- {
- foreach (IvyApplicationBinding bind in bindings.Values)
- {
- if (bind.Expression == re)
- {
- try
- {
- UnbindMsg(bind.Key);
- }
- catch (IvyException)
- {
- return false;
- }
- return true;
- }
- }
- return false;
- }
+ // sends the broadcasts and listen to incoming connexions
+ for (int i = 0; i < watchers.Count; i++)
+ {
+ watchers[i].start();
+ }
+ }
+ internal void SortClients()
+ {
+ lock (clients)
+ {
+ //clients.Sort(new IvyClient.IvyClientPriority());
+ clients.Sort();
+ }
+ }
+
+
+ internal static Domain[] parseDomains(string domainbus)
+ {
+ string[] st = domainbus.Split(',');
+ Domain[] d = new Domain[st.Length];
+ for (int i = 0; i < st.Length; i++)
+ {
+ d[i] = new Domain(st[i]);
+ }
+ return d;
+ }
+
+ /// <summary>
+ /// disconnects from the Ivy bus
+ /// </summary>
+ public void Stop()
+ {
+ if (stopped)
+ return;
+ lock (app)
+ {
+ stopped = true;
+ Ivy.traceProtocol(Resources.Ivy, "beginning stopping the bus");
+ try
+ {
+ // stopping the serverThread
+ if (serverThread != null)
+ {
+ app.Stop();
+ // Wait for Thread to end.
+ bool term = serverThread.Join(10000);
+ if (!term && (serverThread != null)) serverThread.Abort();
+ serverThread = null;
+ }
+ // The serverThread might be stopped even before having been created
+ if (app != null)
+ app.Stop();
+ // stopping the IvyWatchers
+ if (watchers != null)
+ for (int i = 0; i < watchers.Count; i++)
+ {
+ ((IvyWatcher)watchers[i]).stop();
+ }
+ // stopping the remaining IvyClients
+ // copy the values in temporary variable to eliminate Thread modifying collection
+ if (clients.Count != 0)
+ {
+ IvyClient[] copyClient;
+ lock (clients)
+ {
+ copyClient = new IvyClient[clients.Count];
+ clients.CopyTo(copyClient);
+ }
+ foreach (IvyClient client in copyClient)
+ {
+ client.close(true); // will notify the reading thread
+ //removeClient(client); already donne in the thread
+ }
+ }
+ }
+ catch (IOException e)
+ {
+ Ivy.traceError(Resources.Ivy, "IOexception Stop " + e.Message);
+ }
+ Ivy.traceProtocol(Resources.Ivy, "the bus should have stopped so far");
+ }
+ }
+ /// <summary>
+ /// join the main thread of Ivy ( ie wait until stopped )
+ /// </summary>
+ /// <remarks>
+ /// Performs a join on the Principal Thread.
+ /// </remarks>
+ /// <param name='millisecondsTimeout'>Number of millisecondes to wait before the Thread Stop.</param>
+ /// <returns>
+ /// true if the thread stopped; false if it did not stop after the expiry of the period specified by the parameter millisecondsTimeout
+ /// </returns>
+ public bool Join(int millisecondsTimeout)
+ {
+ return serverThread.Join(millisecondsTimeout);
+ }
+ /// <summary>
+ /// Block the calling Thread until Ivy Stop
+ /// </summary>
+ /// <remarks>
+ /// Performs a join on the Principal Thread.
+ /// </remarks>
+ public void MainLoop()
+ {
+ this.Join(Timeout.Infinite);
+ }
+
+ /// <summary>
+ /// Send a formated message to someone on the bus
+ /// </summary>
+ /// <remarks>
+ /// Performs a pattern matching according to everyone's regexps, and sends
+ /// the results to the relevant ivy agents.
+ /// There is one thread for each client connected, we could also
+ /// create another thread each time we send a message.
+ /// </remarks>
+ /// <param name='format'>A string message format to build the message</param>
+ /// <param name='args'>args used in message format</param>
+ /// <returns>
+ /// the number of messages actually sent
+ /// </returns>
+ public int SendMsg(string format, params object[] args)
+ {
+ // send to everybody
+ string msg = string.Format(culture, format, args);
+ int count = 0;
+ // hash message in V4 protocol only
+ if (ProtocolVersion == 4)
+ IvyBindingSimple.Prepare(msg);
+ // an alternate implementation would one sender thread per client
+ // instead of one for all the clients. It might be a performance issue
+ // Tentative of using BeginInvoke EndInvoke is slower
+ lock (client_bindings)
+ {
+ foreach (IvyClientBinding clbind in client_bindings.Values)
+ {
+ string[] matches = clbind.binding.Match(msg);
+ if (matches != null)
+ {
+ lock (clbind.client_bindind_ids)
+ {
+
+ foreach (KeyValuePair<IvyClient, List<int>> assoc in clbind.client_bindind_ids)
+ {
+ foreach (ushort id in assoc.Value)
+ {
+ count += assoc.Key.sendMsg(id, matches);
+ }
+
+ }
+
+ }
+ }
+
+ }
+
+ }
+ return count;
+ }
+
+ internal int SendMsgToClient(IvyClient clnt, string format, params object[] args)
+ {
+ string msg = string.Format(culture, format, args);
+ int count = 0;
+ // hash message in V4 protocol only
+ if (ProtocolVersion == 4)
+ IvyBindingSimple.Prepare(msg);
+ // an alternate implementation would one sender thread per client
+ // instead of one for all the clients. It might be a performance issue
+ lock (client_bindings)
+ {
- /// <summary>
- /// Subscribes to a simple expression ( msg ar1 arg2 arg3 etc).
- /// </summary>
- /// <remarks>
- /// The callback will be executed with
- /// the saved parameters of the regexp as arguments when a message will sent
- /// by another agent. A program doesn't receive its own messages.
- /// </remarks>
- ///
- /// <param name='regexp'>a regular expression, groups are done with parenthesis</param>
- /// <param name='callback'>any objects implementing the EventHandler<IvyMessageEventArgs></param>
- /// <returns>
- /// the id of the regular expression
- /// </returns>
- public int BindSimpleMsg(string expression, EventHandler<IvyMessageEventArgs> callback, params object[] args)
- {
- // creates a new binding (regexp,callback)
- IvyApplicationBinding newbind;
- newbind = new IvyApplicationBinding(BindingType.Simple, expression, args);
- newbind.Callback += callback;
- return BindMsg(newbind);
- }
- /// <summary>
- /// Dies the specified target.
- /// </summary>
- /// <param name="target">The target.</param>
- /// <param name="message">The reason message.</param>
- /// <returns></returns>
- public int Die(string target, string message)
- {
- ReadOnlyCollection<IvyClient> v = GetClientsByName(target);
- foreach (IvyClient clnt in v)
- clnt.stream.TokenDie(0, message);
- return v.Count;
- }
- /// <summary>
- /// Pings the specified target.
- /// </summary>
- /// <param name="target">The target.</param>
- /// <param name="message">The message.</param>
- /// <returns></returns>
- public int Ping(string target, string message)
- {
- int id = (int)DateTime.Now.Ticks;
- ReadOnlyCollection<IvyClient> v = GetClientsByName(target);
- foreach (IvyClient clnt in v)
- {
- clnt.stream.TokenPing(id, message);
- }
- return v.Count;
- }
+ foreach (IvyClientBinding clbind in client_bindings.Values)
+ {
+ string[] matches = clbind.binding.Match(msg);
+ if (matches != null)
+ {
+ lock (clbind.client_bindind_ids)
+ {
+ if (clbind.client_bindind_ids.ContainsKey(clnt))
+ {
+ List<int> ids = clbind.client_bindind_ids[clnt];
+ foreach (ushort id in ids)
+ {
+ count += clnt.sendMsg(id, matches);
+ }
+ }
+ }
+ }
+ }
+ }
+
+
+ return count;
+ }
+ /// <summary>
+ /// Make a binding to a message using regular expresssion
+ /// </summary>
+ /// <param name="newBinding"></param>
+ /// <returns></returns>
+ public int BindMsg(IvyApplicationBinding newBinding)
+ {
+ newBinding.Key = Interlocked.Increment(ref serial);
+
+ lock (bindings) bindings.Add(newBinding.Key, newBinding);
+ // notifies the other clients this new regexp
+ lock (clients)
+ {
+ foreach (IvyClient c in clients)
+ {
+ c.stream.TokenAddBinding(newBinding.Binding, newBinding.Key, newBinding.FormattedExpression);
+ }
+ }
+ return newBinding.Key;
+ }
+ /// <summary>
+ /// Subscribes to a regular expression.
+ /// </summary>
+ /// <param name="regexp">a regular expression, groups are done with parenthesis</param>
+ /// <param name="callback">any objects implementing the EventHandler<IvyMessageEventArgs> </param>
+ /// <param name="args">The args.</param>
+ /// <returns>the id of the regular expression</returns>
+ /// <remarks>
+ /// The callback will be executed with
+ /// the saved parameters of the regexp as arguments when a message will sent
+ /// by another agent. A program doesn't receive its own messages.
+ /// the expression cant containt some dynamics argument replacement of the form %number[:objectFormat]%
+ /// the string will be replaced by arg[number].ToString(objectFormat)
+ /// </remarks>
+ //
+ public int BindMsg(string expression, EventHandler<IvyMessageEventArgs> callback, params object[] args)
+ {
+ // creates a new binding (regexp,callback)
+ IvyApplicationBinding newbind;
+ newbind = new IvyApplicationBinding(BindingType.RegularExpression, expression, args);
+ newbind.Callback += callback;
+ return BindMsg(newbind);
+ }
+
+ /// <summary>
+ /// unsubscribes a regular expression
+ /// </summary>
+ /// <param name="id">the id of the regular expression, returned when it was bound</param>
+ public void UnbindMsg(int id)
+ {
+ if (!bindings.ContainsKey(id))
+ {
+ throw new IvyException("client wants to remove an unexistant regexp " + id);
+ }
+ lock (clients)
+ {
+ foreach (IvyClient c in clients)
+ {
+ try
+ {
+ if ( c.stream != null )
+ c.stream.TokenDelBinding(id);
+ }
+ catch (IOException)
+ {
+ // client closed ignore it
+ }
+ }
+ }
+ lock (bindings) bindings.Remove(id);
+ }
+ /// <summary>
+ /// Change a binding already registred
+ /// </summary>
+ /// <param name="id"></param>
+ /// <param name="expression"></param>
+ /// <returns></returns>
+ public int ChangeMsg(int id, string expression)
+ {
+ IvyApplicationBinding newbind;
+ if (!bindings.ContainsKey(id))
+ {
+ throw new IvyException("client wants to change an unexistant regexp " + id);
+ }
+
+ // change binding (regexp,callback)
+ lock (bindings)
+ {
+ newbind = bindings[id];
+ newbind.Expression = expression;
+ }
+ // notifies the other clients this new regexp
+ lock (clients)
+ {
+ foreach (IvyClient c in clients)
+ {
+ c.stream.TokenAddBinding(newbind.Binding, newbind.Key, newbind.FormattedExpression);
+ }
+ }
+ return id;
+ }
+
+
+ /// <summary>
+ /// unsubscribes a regular expression
+ /// </summary>
+ /// <param name="re">the string for the regular expression</param>
+ /// <returns>
+ /// a boolean, true if the regexp existed, false otherwise or
+ /// whenever an exception occured during unbinding
+ /// </returns>
+ public bool UnbindMsg(string re)
+ {
+ foreach (IvyApplicationBinding bind in bindings.Values)
+ {
+ if (bind.Expression == re)
+ {
+ try
+ {
+ UnbindMsg(bind.Key);
+ }
+ catch (IvyException)
+ {
+ return false;
+ }
+ return true;
+ }
+ }
+ return false;
+ }
+
+
+ /// <summary>
+ /// Subscribes to a simple expression ( msg ar1 arg2 arg3 etc).
+ /// </summary>
+ /// <remarks>
+ /// The callback will be executed with
+ /// the saved parameters of the regexp as arguments when a message will sent
+ /// by another agent. A program doesn't receive its own messages.
+ /// </remarks>
+ ///
+ /// <param name='regexp'>a regular expression, groups are done with parenthesis</param>
+ /// <param name='callback'>any objects implementing the EventHandler<IvyMessageEventArgs></param>
+ /// <returns>
+ /// the id of the regular expression
+ /// </returns>
+ public int BindSimpleMsg(string expression, EventHandler<IvyMessageEventArgs> callback, params object[] args)
+ {
+ // creates a new binding (regexp,callback)
+ IvyApplicationBinding newbind;
+ newbind = new IvyApplicationBinding(BindingType.Simple, expression, args);
+ newbind.Callback += callback;
+ return BindMsg(newbind);
+ }
+ /// <summary>
+ /// Dies the specified target.
+ /// </summary>
+ /// <param name="target">The target.</param>
+ /// <param name="message">The reason message.</param>
+ /// <returns></returns>
+ public int Die(string target, string message)
+ {
+ ReadOnlyCollection<IvyClient> v = GetClientsByName(target);
+ foreach (IvyClient clnt in v)
+ clnt.stream.TokenDie(0, message);
+ return v.Count;
+ }
+ /// <summary>
+ /// Pings the specified target.
+ /// </summary>
+ /// <param name="target">The target.</param>
+ /// <param name="message">The message.</param>
+ /// <returns></returns>
+ public int Ping(string target, string message)
+ {
+ int id = (int)DateTime.Now.Ticks;
+ ReadOnlyCollection<IvyClient> v = GetClientsByName(target);
+ foreach (IvyClient clnt in v)
+ {
+ clnt.stream.TokenPing(id, message);
+ }
+ return v.Count;
+ }
- internal virtual void FireEvent(EventHandler<IvyEventArgs> ev, IvyEventArgs e)
- {
- if (ev != null)
- {
+ internal virtual void FireEvent(EventHandler<IvyEventArgs> ev, IvyEventArgs e)
+ {
+ if (ev != null)
+ {
#if (PocketPC)
- if (parentControl != null)
- {
- parentControl.Invoke(ev, this, e);
- }
+ if (parentControl != null)
+ {
+ parentControl.Invoke(ev, this, e);
+ }
#else
- if (syncContext != null)
- {
- SendOrPostCallback update = delegate(object state)
- {
- IvyEventArgs args = (IvyEventArgs)state;
- ev(this, args);
- };
- syncContext.Post(update, e);
- }
+ if (synchronous)
+ {
+ SendOrPostCallback update = delegate(object state)
+ {
+ IvyEventArgs args = (IvyEventArgs)state;
+ ev(this, args);
+ };
+ syncContext.Post(update, e);
+ }
#endif
- else
- ev(this, e);
- }
- }
-
-
- internal virtual void OnDirectMessage(IvyEventArgs e)
- {
- // Copy to a temporary variable to be thread-safe.
- EventHandler<IvyEventArgs> temp = DirectMessageReceived;
- FireEvent(temp,e);
- }
- internal virtual void OnClientConnected(IvyEventArgs e)
- {
- // Copy to a temporary variable to be thread-safe.
- EventHandler<IvyEventArgs> temp = ClientConnected;
- FireEvent(temp,e);
- }
- internal virtual void OnClientDisconnected(IvyEventArgs e)
- {
- // Copy to a temporary variable to be thread-safe.
- EventHandler<IvyEventArgs> temp = ClientDisconnected;
- try
- {
- FireEvent(temp,e);
- }
+ else
+ ev(this, e);
+ }
+ }
+
+
+ internal virtual void OnDirectMessage(IvyEventArgs e)
+ {
+ // Copy to a temporary variable to be thread-safe.
+ EventHandler<IvyEventArgs> temp = DirectMessageReceived;
+ FireEvent(temp,e);
+ }
+ internal virtual void OnClientConnected(IvyEventArgs e)
+ {
+ // Copy to a temporary variable to be thread-safe.
+ EventHandler<IvyEventArgs> temp = ClientConnected;
+ FireEvent(temp,e);
+ }
+ internal virtual void OnClientDisconnected(IvyEventArgs e)
+ {
+ // Copy to a temporary variable to be thread-safe.
+ EventHandler<IvyEventArgs> temp = ClientDisconnected;
+ try
+ {
+ FireEvent(temp,e);
+ }
#if (!PocketPC)
- catch (SynchronizationLockException)
- {
- // protect terminaison
- }
+ catch (SynchronizationLockException)
+ {
+ // protect terminaison
+ }
#endif
- catch (ObjectDisposedException)
- {
- // protect terminaison
- }
-
- }
- internal virtual void OnClientAddBinding(IvyEventArgs e)
- {
- // Copy to a temporary variable to be thread-safe.
- EventHandler<IvyEventArgs> temp = BindingAdd;
- FireEvent(temp,e);
- }
- internal virtual void OnClientRemoveBinding(IvyEventArgs e)
- {
- // Copy to a temporary variable to be thread-safe.
- EventHandler<IvyEventArgs> temp = BindingRemove;
- FireEvent(temp,e);
- }
- internal virtual void OnClientChangeBinding(IvyEventArgs e)
- {
- // Copy to a temporary variable to be thread-safe.
- EventHandler<IvyEventArgs> temp = BindingChange;
- FireEvent(temp, e);
- }
- internal virtual void OnClientFilterBinding(IvyEventArgs e)
- {
- // Copy to a temporary variable to be thread-safe.
- EventHandler<IvyEventArgs> temp = BindingFilter;
- FireEvent(temp,e);
- }
- internal virtual void OnError(IvyEventArgs e)
- {
- // Copy to a temporary variable to be thread-safe.
- EventHandler<IvyEventArgs> temp = ErrorMessage;
- FireEvent(temp, e);
- }
+ catch (ObjectDisposedException)
+ {
+ // protect terminaison
+ }
+
+ }
+ internal virtual void OnClientAddBinding(IvyEventArgs e)
+ {
+ // Copy to a temporary variable to be thread-safe.
+ EventHandler<IvyEventArgs> temp = BindingAdd;
+ FireEvent(temp,e);
+ }
+ internal virtual void OnClientRemoveBinding(IvyEventArgs e)
+ {
+ // Copy to a temporary variable to be thread-safe.
+ EventHandler<IvyEventArgs> temp = BindingRemove;
+ FireEvent(temp,e);
+ }
+ internal virtual void OnClientChangeBinding(IvyEventArgs e)
+ {
+ // Copy to a temporary variable to be thread-safe.
+ EventHandler<IvyEventArgs> temp = BindingChange;
+ FireEvent(temp, e);
+ }
+ internal virtual void OnClientFilterBinding(IvyEventArgs e)
+ {
+ // Copy to a temporary variable to be thread-safe.
+ EventHandler<IvyEventArgs> temp = BindingFilter;
+ FireEvent(temp,e);
+ }
+ internal virtual void OnError(IvyEventArgs e)
+ {
+ // Copy to a temporary variable to be thread-safe.
+ EventHandler<IvyEventArgs> temp = ErrorMessage;
+ FireEvent(temp, e);
+ }
#if (PocketPC)
- internal virtual void OnDie(IvyDieEventArgs e)
- {
- // Copy to a temporary variable to be thread-safe.
- EventHandler<IvyDieEventArgs> temp = DieReceived;
- if (temp != null)
- {
- if (parentControl != null)
- {
- parentControl.Invoke(temp, this, e);
- }
- else
- temp(this, e);
- }
- }
+ internal virtual void OnDie(IvyDieEventArgs e)
+ {
+ // Copy to a temporary variable to be thread-safe.
+ EventHandler<IvyDieEventArgs> temp = DieReceived;
+ if (temp != null)
+ {
+ if (parentControl != null)
+ {
+ parentControl.Invoke(temp, this, e);
+ }
+ else
+ temp(this, e);
+ }
+ }
#else
- internal virtual void OnDie(IvyDieEventArgs e)
- {
- // Copy to a temporary variable to be thread-safe.
- EventHandler<IvyDieEventArgs> temp = DieReceived;
- if (temp != null)
- {
- if (syncContext != null)
- {
- SendOrPostCallback update = delegate(object state)
- {
- IvyDieEventArgs args = (IvyDieEventArgs)state;
- temp(this, args);
- };
- syncContext.Post(update, e);
- }
- else
- temp(this, e);
- }
- }
+ internal virtual void OnDie(IvyDieEventArgs e)
+ {
+ // Copy to a temporary variable to be thread-safe.
+ EventHandler<IvyDieEventArgs> temp = DieReceived;
+ if (temp != null)
+ {
+ if (syncContext != null)
+ {
+ SendOrPostCallback update = delegate(object state)
+ {
+ IvyDieEventArgs args = (IvyDieEventArgs)state;
+ temp(this, args);
+ };
+ syncContext.Post(update, e);
+ }
+ else
+ temp(this, e);
+ }
+ }
#endif
- internal void OnMessage(IvyMessageEventArgs e)
- {
- if (!bindings.ContainsKey( e.Id))
- {
- throw new IvyException("(callCallback) Not regexp matching id " + e.Id);
- }
- IvyApplicationBinding bind = bindings[e.Id];
+ internal void OnMessage(IvyMessageEventArgs e)
+ {
+ if (!bindings.ContainsKey( e.Id))
+ {
+ throw new IvyException("(callCallback) Not regexp matching id " + e.Id);
+ }
+ IvyApplicationBinding bind = bindings[e.Id];
#if(PocketPC)
- bind.Firevent(parentControl, e);
+ bind.Firevent(parentControl, e);
#else
- bind.Firevent(syncContext, e);
+ bind.Firevent(syncContext,synchronous, e);
#endif
- }
-
- /*
- * removes a client from the list
- */
- internal void removeClient(IvyClient c)
- {
- lock (clients)
- {
- clients.Remove(c);
- }
- List<string> purge_bind = new List<string>();
- lock (client_bindings)
- {
- foreach (IvyClientBinding clbind in client_bindings.Values)
- {
- lock (clbind.client_bindind_ids)
- {
- clbind.client_bindind_ids.Remove(c);
- if ( clbind.client_bindind_ids.Count == 0 )
- purge_bind.Add( clbind.binding.Expression);
- }
- }
- // remove Binding if no client
- foreach ( string expr in purge_bind )
- {
- client_bindings.Remove(expr);
- }
- }
- }
-
-
- /// <summary>
- /// gives a list of IvyClient(s) with the name given in parameter
- /// </summary>
- /// <param name="name">The name of the Ivy agent you're looking for</param>
- /// <returns></returns>
- public ReadOnlyCollection<IvyClient> GetClientsByName(string name)
- {
- List<IvyClient> v = new List<IvyClient>();
- foreach (IvyClient ic in clients)
- {
- if (ic.ApplicationName.CompareTo(name) == 0)
- v.Add(ic);
- }
- return new ReadOnlyCollection<IvyClient>(v);
- }
-
- /////////////////////////////////////////////////////////////////:
- //
- // Protected methods
- //
- /////////////////////////////////////////////////////////////////:
-
- internal void addClient(IvyClient client)
- {
- if (stopped)
- return;
-
- lock (clients)
- {
- clients.Add(client);
- }
-
- }
-
- /// <summary>
- /// return the first non loopback adress
- /// on a one network interface machine it will be my IP adresse
- /// </summary>
- public static IPAddress LocalIP
- {
- get
- {
- IPAddress returnaddr = null;
- //TODO remove ALL reverse DNS search !!!!
- IPHostEntry ip = Dns.GetHostEntry(Dns.GetHostName());
- foreach (IPAddress addr in ip.AddressList)
- {
- returnaddr = addr;
- if (IPAddress.IsLoopback(addr)) continue;
- break;
- }
- return returnaddr;
- }
- }
- /// <summary>
- /// Get the FDQN Domain from a string
- /// </summary>
- /// <param name="domainBus"></param>
- /// <returns></returns>
- public static string GetDomain(string domainBus)
- {
+ }
+
+ /*
+ * removes a client from the list
+ */
+ internal void removeClient(IvyClient c)
+ {
+ lock (clients)
+ {
+ clients.Remove(c);
+ }
+ List<string> purge_bind = new List<string>();
+ lock (client_bindings)
+ {
+ foreach (IvyClientBinding clbind in client_bindings.Values)
+ {
+ lock (clbind.client_bindind_ids)
+ {
+ clbind.client_bindind_ids.Remove(c);
+ if ( clbind.client_bindind_ids.Count == 0 )
+ purge_bind.Add( clbind.binding.Expression);
+ }
+ }
+ // remove Binding if no client
+ foreach ( string expr in purge_bind )
+ {
+ client_bindings.Remove(expr);
+ }
+ }
+ }
+
+
+ /// <summary>
+ /// gives a list of IvyClient(s) with the name given in parameter
+ /// </summary>
+ /// <param name="name">The name of the Ivy agent you're looking for</param>
+ /// <returns></returns>
+ public ReadOnlyCollection<IvyClient> GetClientsByName(string name)
+ {
+ List<IvyClient> v = new List<IvyClient>();
+ foreach (IvyClient ic in clients)
+ {
+ if (ic.ApplicationName.CompareTo(name) == 0)
+ v.Add(ic);
+ }
+ return new ReadOnlyCollection<IvyClient>(v);
+ }
+
+ /////////////////////////////////////////////////////////////////:
+ //
+ // Protected methods
+ //
+ /////////////////////////////////////////////////////////////////:
+
+ internal void addClient(IvyClient client)
+ {
+ if (stopped)
+ return;
+
+ lock (clients)
+ {
+ clients.Add(client);
+ }
+
+ }
+
+ /// <summary>
+ /// return the first non loopback adress
+ /// on a one network interface machine it will be my IP adresse
+ /// </summary>
+ public static IPAddress LocalIP
+ {
+ get
+ {
+ IPAddress returnaddr = null;
+ //TODO remove ALL reverse DNS search !!!!
+ IPHostEntry ip = Dns.GetHostEntry(Dns.GetHostName());
+ foreach (IPAddress addr in ip.AddressList)
+ {
+ returnaddr = addr;
+ if (IPAddress.IsLoopback(addr)) continue;
+ break;
+ }
+ return returnaddr;
+ }
+ }
+ /// <summary>
+ /// Get the FDQN Domain from a string
+ /// </summary>
+ /// <param name="domainBus"></param>
+ /// <returns></returns>
+ public static string GetDomain(string domainBus)
+ {
#if (PocketPC) // TODO integrate in normal version
- if (domainbus == null || domainbus.Length == 0)
- {
- IPAddress addr = GetLocalIP();
- //TODO Find Braodcast addr from IP;
- byte[] bytes = addr.GetAddressBytes();
- if (IPAddress.IsLoopback(addr))
- {
- // 127.255.255.255
- bytes[1] = 255;
- bytes[2] = 255;
- bytes[3] = 255;
- }
- else
- {
- // else assume class C network
- // TODO find exact netmask
- bytes[3] = 255;
- }
- IPAddress bcast = new IPAddress(bytes);
- domainbus = bcast + ":" + Domain.getPort(domainbus);
- }
+ if (domainbus == null || domainbus.Length == 0)
+ {
+ IPAddress addr = GetLocalIP();
+ //TODO Find Braodcast addr from IP;
+ byte[] bytes = addr.GetAddressBytes();
+ if (IPAddress.IsLoopback(addr))
+ {
+ // 127.255.255.255
+ bytes[1] = 255;
+ bytes[2] = 255;
+ bytes[3] = 255;
+ }
+ else
+ {
+ // else assume class C network
+ // TODO find exact netmask
+ bytes[3] = 255;
+ }
+ IPAddress bcast = new IPAddress(bytes);
+ domainbus = bcast + ":" + Domain.getPort(domainbus);
+ }
#else
- if (domainBus == null || domainBus.Length == 0 )
+ if (domainBus == null || domainBus.Length == 0 )
{
domainBus = Environment.GetEnvironmentVariable("IVYBUS");
}
- if (domainBus == null || domainBus.Length == 0)
- {
- domainBus = Properties.Settings.Default.IvyBus;
- }
+ if (domainBus == null || domainBus.Length == 0)
+ {
+ domainBus = Properties.Settings.Default.IvyBus;
+ }
#endif
- if (domainBus == null || domainBus.Length == 0)
- domainBus = DefaultDomain;
- return domainBus;
- }
-
-
- /// checks the "validity" of a regular expression. //TODO put in IvyBinding
- internal bool CheckRegexp(string exp)
- {
- bool regexp_ok = true;
- // Attention Bug
- // ClockStop ClockStart & ^Clock(Start|Pause)
- // should Stop to the first parent
- if ((sent_messageFilter.Count != 0) && exp.StartsWith("^"))
- {
- regexp_ok = false;
- // extract first word from regexp...
- string token = Regex.Replace(exp, @"^\^(?<token>[a-zA-Z_0-9-]+).*", @"${token}");
-
- foreach (string exp_class in sent_messageFilter)
- {
- if (exp_class.StartsWith(token))
- return true;
- }
- }
- return regexp_ok;
- }
+ if (domainBus == null || domainBus.Length == 0)
+ domainBus = DefaultDomain;
+ return domainBus;
+ }
+
+
+ /// checks the "validity" of a regular expression. //TODO put in IvyBinding
+ internal bool CheckRegexp(string exp)
+ {
+ bool regexp_ok = true;
+ // Attention Bug
+ // ClockStop ClockStart & ^Clock(Start|Pause)
+ // should Stop to the first parent
+ if ((sent_messageFilter.Count != 0) && exp.StartsWith("^"))
+ {
+ regexp_ok = false;
+ // extract first word from regexp...
+ string token = Regex.Replace(exp, @"^\^(?<token>[a-zA-Z_0-9-]+).*", @"${token}");
+
+ foreach (string exp_class in sent_messageFilter)
+ {
+ if (exp_class.StartsWith(token))
+ return true;
+ }
+ }
+ return regexp_ok;
+ }
+
+ /*
+ * prevents two clients from connecting to each other at the same time
+ * there might still be a lingering bug here, that we could avoid with the
+ * SchizoToken.
+ */
+ internal IvyClient checkConnected(IvyClient clnt)
+ {
+ IvyClient sameClnt = null;
+ if (clnt.AppPort == 0)
+ {
+ Console.WriteLine(" client {0} port == 0 ", clnt.appName);
+ return sameClnt;
+ }
+ lock (clients)
+ {
+ foreach (IvyClient client in clients)
+ {
+ if (clnt == client) continue; // SKIP himself
+ if (client.sameIvyClient(clnt))
+ {
+ sameClnt = client;
+ break;
+ }
+ }
+ }
+ return sameClnt;
+ }
+
+ /*
+ * the service socket thread reader main loop
+ */
+ private void TcpListener()
+ {
+ Ivy.traceProtocol(Resources.Ivy, "Ivy service Thread started");
+ bool running = true;
+ tcplistener_running.Set();
+ while (running)
+ {
+ try
+ {
+ Socket socket = app.AcceptSocket();
+ // early disconnexion
+ if (stopped)
+ break;
+ // the peer called me
+ IvyClient client = new IvyClient(this, socket, "Unkown(waiting for name reception)",0);
+ client.SendBindings(); //TODO in a Thread or wait for the peer to sent his before sending mine
+
+ }
+ catch (IOException e)
+ {
+ Ivy.traceError(Resources.Ivy,Resources.IvyIOException + e.Message);
+ }
+ catch (SocketException e)
+ {
+ Ivy.traceError(Resources.Ivy,Resources.IvySocketException + e.Message);
+ running = false;
+ }
+ }
+ Ivy.traceProtocol(Resources.Ivy, "Ivy service Thread stopped");
+ }
+
+ [Conditional("DEBUG")]
+ internal static void traceProtocol(string name, string message)
+ {
+ if ( debugProtocol )
+ Console.WriteLine( "-->{0}<-- {1}", name, message);
+ }
+ internal static void traceError(string name, string message)
+ {
+ Console.WriteLine("-->{0}<-- {1}", name, message);
+ }
+
+ internal class Domain
+ {
+ public virtual string Domainaddr
+ {
+ get
+ {
+ return domainaddr;
+ }
- /*
- * prevents two clients from connecting to each other at the same time
- * there might still be a lingering bug here, that we could avoid with the
- * SchizoToken.
- */
- internal IvyClient checkConnected(IvyClient clnt)
- {
- IvyClient sameClnt = null;
- if (clnt.AppPort == 0)
- {
- Console.WriteLine(" client {0} port == 0 ", clnt.appName);
- return sameClnt;
- }
- lock (clients)
- {
- foreach (IvyClient client in clients)
- {
- if (clnt == client) continue; // SKIP himself
- if (client.sameIvyClient(clnt))
- {
- sameClnt = client;
- break;
- }
- }
- }
- return sameClnt;
- }
+ }
+ public virtual int Port
+ {
+ get
+ {
+ return port;
+ }
- /*
- * the service socket thread reader main loop
- */
- private void TcpListener()
- {
- Ivy.traceProtocol(Resources.Ivy, "Ivy service Thread started");
- bool running = true;
- tcplistener_running.Set();
- while (running)
- {
- try
- {
- Socket socket = app.AcceptSocket();
- // early disconnexion
- if (stopped)
- break;
- // the peer called me
- IvyClient client = new IvyClient(this, socket, "Unkown(waiting for name reception)",0);
- client.SendBindings(); //TODO in a Thread or wait for the peer to sent his before sending mine
-
- }
- catch (IOException e)
- {
- Ivy.traceError(Resources.Ivy,Resources.IvyIOException + e.Message);
- }
- catch (SocketException e)
- {
- Ivy.traceError(Resources.Ivy,Resources.IvySocketException + e.Message);
- running = false;
- }
- }
- Ivy.traceProtocol(Resources.Ivy, "Ivy service Thread stopped");
- }
+ }
+ private string domainaddr;
+ private int port;
+ public Domain(string net):this( getDomain(net),getPort(net))
+ {
+ }
+ public Domain(string domainaddr, int port)
+ {
+ this.domainaddr = domainaddr;
+ this.port = port;
+ }
+ public override string ToString()
+ {
+ return domainaddr + ":" + port;
+ }
+ public static string getDomain(string net)
+ {
+ int sep_index = net.LastIndexOf(":");
+ if (sep_index != -1)
+ {
+ net = net.Substring(0, (sep_index) - (0));
+ }
+ try
+ {
+ if (!net.Contains("::")) // if not IPV6 multicast paste with 255
+ {
+ net += ".255.255.255";
+ Regex exp = new Regex("^(\\d+\\.\\d+\\.\\d+\\.\\d+).*");
+ net = exp.Replace(net, "$1");
+ }
+ }
+ catch (ArgumentException e)
+ {
+ Ivy.traceError(Resources.Ivy,Resources.BadBroadcast + net + "error " + e.Message);
+ return null;
+ }
+ return net;
+ }
- [Conditional("DEBUG")]
- internal static void traceProtocol(string name, string message)
- {
- if ( debugProtocol )
- Console.WriteLine( "-->{0}<-- {1}", name, message);
- }
- internal static void traceError(string name, string message)
- {
- Console.WriteLine("-->{0}<-- {1}", name, message);
- }
+ public static int getPort(string net)
+ {
+ if (net == null) { return Ivy.DefaultPort; }
+ int sep_index = net.LastIndexOf(":");
+ int port = (sep_index == -1) ? Ivy.DefaultPort : Int32.Parse(net.Substring(sep_index + 1));
+ return port;
+ }
+ }
- internal class Domain
+ /// <summary>
+ /// check Validity of Ivy Bus Domain
+ /// </summary>
+ /// <param name="domain"></param>
+ /// <returns></returns>
+ public static bool ValidatingDomain(string domain)
{
- public virtual string Domainaddr
- {
- get
- {
- return domainaddr;
- }
-
- }
- public virtual int Port
- {
- get
- {
- return port;
- }
-
- }
- private string domainaddr;
- private int port;
- public Domain(string net):this( getDomain(net),getPort(net))
- {
- }
- public Domain(string domainaddr, int port)
+ IPAddress result;
+ bool valid = false;
+ string addr = Domain.getDomain(domain);
+ try
{
- this.domainaddr = domainaddr;
- this.port = port;
+ int port = Domain.getPort(domain);
+ if (port < IPEndPoint.MinPort || port > IPEndPoint.MaxPort) return false;
}
- public override string ToString()
+ catch (OverflowException e)
{
- return domainaddr + ":" + port;
+ return false;
}
- public static string getDomain(string net)
+ if (String.IsNullOrEmpty(addr))
{
- 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)
- {
- Ivy.traceError(Resources.Ivy,Resources.BadBroadcast + net + "error " + e.Message);
- return null;
- }
- return net;
+ // address wasnt provided so return false
+ valid = false;
}
-
- public static int getPort(string net)
+ else
{
- if (net == null) { return Ivy.DefaultPort; }
- int sep_index = net.LastIndexOf(":");
- int port = (sep_index == -1) ? Ivy.DefaultPort : Int32.Parse(net.Substring(sep_index + 1));
- return port;
+ //use TryParse to see if this is a
+ //valid ip address. TryParse returns a
+ //boolean based on the validity of the
+ //provided address, so assign that value
+ //to our boolean variable
+ valid = IPAddress.TryParse(addr, out result);
}
+ return valid;
}
- /// <summary>
- /// check Validity of Ivy Bus Domain
- /// </summary>
- /// <param name="domain"></param>
- /// <returns></returns>
- public static bool ValidatingDomain(string domain)
- {
- // domain if of the form ip1[:port][,ip2[:port]] with ip of the form n1.n2.n3.n4
- return Regex.IsMatch(domain, @"\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}:\d+");
- }
-
- }
+ }
} \ No newline at end of file
diff --git a/Ivy/IvyApplicationBinding.cs b/Ivy/IvyApplicationBinding.cs
index b8932c8..d282583 100644
--- a/Ivy/IvyApplicationBinding.cs
+++ b/Ivy/IvyApplicationBinding.cs
@@ -147,7 +147,7 @@ namespace IvyBus
temp(this, e);
}
#else
- internal void Firevent(System.Threading.SynchronizationContext syncContext, IvyMessageEventArgs e)
+ internal void Firevent(System.Threading.SynchronizationContext syncContext, bool synchronous , IvyMessageEventArgs e)
{
//// Safely invoke an event:
EventHandler<IvyMessageEventArgs> temp = Callback;
@@ -156,7 +156,7 @@ namespace IvyBus
{
throw new IvyException("(callCallback) Not callback for id " + e.Id);
}
- if (syncContext != null)
+ if (synchronous )
{
SendOrPostCallback update = delegate(object state)
{
diff --git a/Ivy/IvyClient.cs b/Ivy/IvyClient.cs
index 98d7901..7a34070 100644
--- a/Ivy/IvyClient.cs
+++ b/Ivy/IvyClient.cs
@@ -7,17 +7,17 @@ namespace IvyBus
{
using System;
using System.Collections;
- using System.Collections.Specialized;
- using System.Collections.Generic;
+ using System.Collections.Specialized;
+ using System.Collections.Generic;
using System.Threading;
using System.Text;
using System.IO;
using System.Net;
using System.Net.Sockets;
using System.Configuration;
- using System.Diagnostics;
- using System.Collections.ObjectModel;
- using IvyBus.Properties;
+ using System.Diagnostics;
+ using System.Collections.ObjectModel;
+ using IvyBus.Properties;
/// <summary> A Class for the the peers on the bus.
/// </summary>
@@ -27,19 +27,19 @@ namespace IvyBus
/// die messages, direct messages, add or remove regexps, or quit. A thread is
/// created for each remote client.
/// </remarks>
- public class IvyClient : IvyProtocol, IComparable<IvyClient>, IDisposable
+ public class IvyClient : IvyProtocol, IComparable<IvyClient>, IDisposable
{
- public int CompareTo(IvyClient other)
- {
- if (other == null)
- return clientPriority;
- else
- return (other.clientPriority - clientPriority);
- }
-
- /// <summary>
- /// the client application Name
- /// </summary>
+ public int CompareTo(IvyClient other)
+ {
+ if (other == null)
+ return clientPriority;
+ else
+ return (other.clientPriority - clientPriority);
+ }
+
+ /// <summary>
+ /// the client application Name
+ /// </summary>
public String ApplicationName
{
get
@@ -49,20 +49,20 @@ namespace IvyBus
}
- //public ReadOnlyCollection<string> Regexps
- //{
- // get
- // {
- // List<string> tab = new List<string>();
- // lock (bindings)
- // {
- // foreach (IvyBindingBase bind in bindings.Values)
- // tab.Add(bind.Expression);
- // }
- // return new ReadOnlyCollection<string>(tab);
- // }
+ //public ReadOnlyCollection<string> Regexps
+ //{
+ // get
+ // {
+ // List<string> tab = new List<string>();
+ // lock (bindings)
+ // {
+ // foreach (IvyBindingBase bind in bindings.Values)
+ // tab.Add(bind.Expression);
+ // }
+ // return new ReadOnlyCollection<string>(tab);
+ // }
- //}
+ //}
internal int AppPort
{
get
@@ -71,145 +71,146 @@ namespace IvyBus
}
}
- /// <summary>
- /// adress of the client
- /// </summary>
- public IPAddress RemoteAddress
+ /// <summary>
+ /// adress of the client
+ /// </summary>
+ public IPAddress RemoteAddress
{
get
{
- return remoteHost;
+ return remoteHost;
}
}
- /// <summary>
- /// port of the client
- /// </summary>
+ /// <summary>
+ /// port of the client
+ /// </summary>
public int RemotePort
{
get
{
- return remotePort;
+ return remotePort;
}
}
private Ivy bus;
- //private Dictionary<ushort,IvyBindingBase> bindings;
+ //private Dictionary<ushort,IvyBindingBase> bindings;
private int appPort;
- private string clientId; /* an unique ID for each IvyClient */
+ private string clientId; /* an unique ID for each IvyClient */
private int clientPriority; /* client priority */
-
+
private volatile Thread clientThread; // volatile to ensure the quick communication
- private bool doping; // false by runtime default
+ private bool doping; // false by runtime default
private const int PINGTIMEOUT = 5000;
private volatile Thread pingerThread;
- private int localPort;
+ private int localPort;
- private int remotePort;
- private IPAddress remoteHost;
+ private int remotePort;
+ private IPAddress remoteHost;
private int readyToSend;
- private Object readyToSendLock;
+ private Object readyToSendLock;
// protected variables
internal String appName;
- internal IvyProtocol stream;
+ internal IvyProtocol stream;
internal IvyClient(Ivy bus, Socket socket, string appname, int appPort)
{
//bindings = new Dictionary<ushort,IvyBindingBase>();
this.appName = appname;
- this.appPort = appPort;
+ this.appPort = appPort;
this.bus = bus;
- readyToSendLock = new Object();
- this.readyToSend = 0;
-
- // set TCP_NODELAY to lower latency
- socket.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.NoDelay, true);
- localPort = ((IPEndPoint)socket.LocalEndPoint).Port;
-
- IPEndPoint endpoint = (IPEndPoint)socket.RemoteEndPoint;
- remoteHost = endpoint.Address;
- remotePort = endpoint.Port;
-
- if ( bus.ProtocolVersion == 4 )
- stream = new IvyTCPStreamV4( socket, this );
- else
- stream = new IvyTCPStreamV3(socket, this);
+ readyToSendLock = new Object();
+ this.readyToSend = 0;
+
+ // set TCP_NODELAY to lower latency
+ //socket.SetSocketOption( SocketOptionLevel.IP, SocketOptionName.NoDelay, true);
+ socket.NoDelay = true;
+ localPort = ((IPEndPoint)socket.LocalEndPoint).Port;
+
+ IPEndPoint endpoint = (IPEndPoint)socket.RemoteEndPoint;
+ remoteHost = endpoint.Address;
+ remotePort = endpoint.Port;
+
+ if ( bus.ProtocolVersion == 4 )
+ stream = new IvyTCPStreamV4( socket, this );
+ else
+ stream = new IvyTCPStreamV3(socket, this);
// spawns a thread to manage the incoming traffic on this
- // socket. We should be ready to receive messages now.
- clientThread = new Thread(new ThreadStart(this.Run));
- clientThread.Name = "Ivy Tcp Client Reader Thread ("+appname+")";
-
- bus.addClient(this);
-
- clientThread.Start();
-
- }
-
- internal void SendBindings()
- {
- try
- {
-
- // sends our ID, whether we initiated the connexion or not
- // the ID is the couple "host name,application Port", the host name
- // information is in the socket itself, the port is not known if we
- // initiate the connexion
- stream.TokenStartRegexp(bus.applicationPort, bus.appName);
- // sends our regexps to the peer
- lock (bus.bindings)
- {
- foreach (IvyApplicationBinding bind in bus.bindings.Values)
- {
- stream.TokenAddBinding(bind.Binding, bind.Key, bind.FormattedExpression);
- }
- }
- // send end of bindings peers can now send ReadyMessage
- stream.TokenEndRegexp();
- // try to send Ready Msg
- SendReadyToPeer();
+ // socket. We should be ready to receive messages now.
+ clientThread = new Thread(new ThreadStart(this.Run));
+ clientThread.Name = "Ivy Tcp Client Reader Thread ("+appname+")";
+
+ bus.addClient(this);
+
+ clientThread.Start();
+
+ }
+
+ internal void SendBindings()
+ {
+ try
+ {
+
+ // sends our ID, whether we initiated the connexion or not
+ // the ID is the couple "host name,application Port", the host name
+ // information is in the socket itself, the port is not known if we
+ // initiate the connexion
+ stream.TokenStartRegexp(bus.applicationPort, bus.appName);
+ // sends our regexps to the peer
+ lock (bus.bindings)
+ {
+ foreach (IvyApplicationBinding bind in bus.bindings.Values)
+ {
+ stream.TokenAddBinding(bind.Binding, bind.Key, bind.FormattedExpression);
+ }
+ }
+ // send end of bindings peers can now send ReadyMessage
+ stream.TokenEndRegexp();
+ // try to send Ready Msg
+ SendReadyToPeer();
#if (!PocketPC)
- doping = Properties.Settings.Default.IvyPing;
+ doping = Properties.Settings.Default.IvyPing;
#endif
- if (doping)
- {
- pingerThread = new Thread(new ThreadStart(PingerRun));
- pingerThread.Name = "Ivy Pinger Thread";
- pingerThread.Start();
- }
-
-
- }
- catch (NullReferenceException ex)
- {
- // the client nous a coupé l'herbe sous le pied
- Ivy.traceError(Resources.IvyClient, Resources.IvyClientLeft + " " + appName + " " + ex.Message);
- // connexion close in rare concurrent connexion
- close(false);
- }
- catch (ObjectDisposedException ex)
- {
- // the client nous a coupé l'herbe sous le pied
- Ivy.traceError(Resources.IvyClient, Resources.IvyClientLeft + " " + appName + " " + ex.Message);
- // invokes the Disconnected applicationListeners
- //bus.OnClientDisconnected(new IvyEventArgs(this,id, message ));
- // called by the receiver Thread
- close(false);
- }
- catch (IOException ex)
- {
- // the client nous a coupé l'herbe sous le pied
- Ivy.traceError(Resources.IvyClient, Resources.IvyClientLeft + " " + appName + " " + ex.Message);
- // invokes the Disconnected applicationListeners
- //bus.OnClientDisconnected(new IvyEventArgs(this,id, message ));
- // called by the receiver Thread
- close(false);
- }
-
- }
+ if (doping)
+ {
+ pingerThread = new Thread(new ThreadStart(PingerRun));
+ pingerThread.Name = "Ivy Pinger Thread";
+ pingerThread.Start();
+ }
+
+
+ }
+ catch (NullReferenceException ex)
+ {
+ // the client nous a coupé l'herbe sous le pied
+ Ivy.traceError(Resources.IvyClient, Resources.IvyClientLeft + " " + appName + " " + ex.Message);
+ // connexion close in rare concurrent connexion
+ close(false);
+ }
+ catch (ObjectDisposedException ex)
+ {
+ // the client nous a coupé l'herbe sous le pied
+ Ivy.traceError(Resources.IvyClient, Resources.IvyClientLeft + " " + appName + " " + ex.Message);
+ // invokes the Disconnected applicationListeners
+ //bus.OnClientDisconnected(new IvyEventArgs(this,id, message ));
+ // called by the receiver Thread
+ close(false);
+ }
+ catch (IOException ex)
+ {
+ // the client nous a coupé l'herbe sous le pied
+ Ivy.traceError(Resources.IvyClient, Resources.IvyClientLeft + " " + appName + " " + ex.Message);
+ // invokes the Disconnected applicationListeners
+ //bus.OnClientDisconnected(new IvyEventArgs(this,id, message ));
+ // called by the receiver Thread
+ close(false);
+ }
+
+ }
/// <summary> returns the name of the remote agent.
/// allow an Ivy package class to access the list of regexps at a
@@ -225,11 +226,11 @@ namespace IvyBus
/// <param name='message'>the string that will be match-tested
///
/// </param>
- public void SendDirectMsg(int id, string message)
+ public void SendDirectMsg(int id, string message)
{
try
{
- stream.TokenDirectMsg( id, message);
+ stream.TokenDirectMsg( id, message);
}
catch (IOException ex)
{
@@ -237,8 +238,8 @@ namespace IvyBus
// first, I'm not a first class IvyClient any more
bus.removeClient(this);
// invokes the Disconnected applicationListeners
- //bus.OnClientDisconnected(new IvyEventArgs(this,id, message ));
- // should be called by receiver thread
+ //bus.OnClientDisconnected(new IvyEventArgs(this,id, message ));
+ // should be called by receiver thread
close(false);
}
}
@@ -252,66 +253,66 @@ namespace IvyBus
internal void close(bool notify)
{
Ivy.traceProtocol(Resources.IvyClient,Resources.Closing + appName);
- if (doping )
+ if (doping )
{
StopPinging();
}
if (notify)
- try
- {
- if (stream != null)
- stream.TokenBye(0, Resources.ByeMessage);
- }
- catch (ObjectDisposedException)
- {
- }
- catch (IOException ioe)
- {
- SocketException se = ioe.InnerException as SocketException;
- if (se != null)
- {
- if (!(se.SocketErrorCode == SocketError.ConnectionReset ||
- se.SocketErrorCode == SocketError.ConnectionAborted))
-
- throw new IvyException(ioe.Message);
- }
- else
- {
- throw new IvyException(ioe.Message);
- }
-
- }
- // stop the thread and close the stream
- if (clientThread == null)
- return;
- // Tell Thread to stop.
- if (stream != null)
- {
- try
- {
- stream.Close(); // should stop the Reading Client Thread
- }
- catch (EndOfStreamException ioe)
- {
- throw new IvyException(ioe.Message);
- }
- catch (IOException ioe)
- {
- throw new IvyException(ioe.Message);
- }
- //socket.Close(); // pris en charge par stream ( NetWorkStream )
- stream = null;
- }
- // Potential dead lok when thread issue ClientDisconnected event
- //if (Thread.CurrentThread != clientThread && (clientThread != null))
- //{
- // // Wait for Thread to end.
- // bool term = clientThread.Join(10000);
- // if (!term && (clientThread != null)) clientThread.Abort();
- //}
-
- clientThread = null;
-
+ try
+ {
+ if (stream != null)
+ stream.TokenBye(0, Resources.ByeMessage);
+ }
+ catch (ObjectDisposedException)
+ {
+ }
+ catch (IOException ioe)
+ {
+ SocketException se = ioe.InnerException as SocketException;
+ if (se != null)
+ {
+ if (!(se.SocketErrorCode == SocketError.ConnectionReset ||
+ se.SocketErrorCode == SocketError.ConnectionAborted))
+
+ throw new IvyException(ioe.Message);
+ }
+ else
+ {
+ throw new IvyException(ioe.Message);
+ }
+
+ }
+ // stop the thread and close the stream
+ if (clientThread == null)
+ return;
+ // Tell Thread to stop.
+ if (stream != null)
+ {
+ try
+ {
+ stream.Close(); // should stop the Reading Client Thread
+ }
+ catch (EndOfStreamException ioe)
+ {
+ throw new IvyException(ioe.Message);
+ }
+ catch (IOException ioe)
+ {
+ throw new IvyException(ioe.Message);
+ }
+ //socket.Close(); // pris en charge par stream ( NetWorkStream )
+ stream = null;
+ }
+ // Potential dead lok when thread issue ClientDisconnected event
+ //if (Thread.CurrentThread != clientThread && (clientThread != null))
+ //{
+ // // Wait for Thread to end.
+ // bool term = clientThread.Join(10000);
+ // if (!term && (clientThread != null)) clientThread.Abort();
+ //}
+
+ clientThread = null;
+
}
@@ -327,34 +328,34 @@ namespace IvyBus
int count = 0;
- try
- {
- if (stream != null)
- {
- stream.TokenMsg(id, args);
- count++;
- }
- }
- catch (ObjectDisposedException ex)
- {
- Ivy.traceError(Resources.IvyClient, Resources.IvyClientLeft + ex.Message);
- // first, I'm not a first class IvyClient any more
- bus.removeClient(this); //TODO trouble in upper loop iter
- // invokes the Disconnected applicationListeners
- // in the receiver thread
- close(false);
- }
- catch (IOException ex)
- {
- Ivy.traceError(Resources.IvyClient, Resources.IvyClientLeft + ex.Message);
- // first, I'm not a first class IvyClient any more
- bus.removeClient(this); //TODO trouble in upper loop iter
- // invokes the Disconnected applicationListeners
- // in the receiver thread
- close(false);
- }
+ try
+ {
+ if (stream != null)
+ {
+ stream.TokenMsg(id, args);
+ count++;
+ }
+ }
+ catch (ObjectDisposedException ex)
+ {
+ Ivy.traceError(Resources.IvyClient, Resources.IvyClientLeft + ex.Message);
+ // first, I'm not a first class IvyClient any more
+ bus.removeClient(this); //TODO trouble in upper loop iter
+ // invokes the Disconnected applicationListeners
+ // in the receiver thread
+ close(false);
+ }
+ catch (IOException ex)
+ {
+ Ivy.traceError(Resources.IvyClient, Resources.IvyClientLeft + ex.Message);
+ // first, I'm not a first class IvyClient any more
+ bus.removeClient(this); //TODO trouble in upper loop iter
+ // invokes the Disconnected applicationListeners
+ // in the receiver thread
+ close(false);
+ }
-
+
return count;
}
@@ -369,9 +370,9 @@ namespace IvyBus
/// </returns>
internal bool sameIvyClient(IvyClient clnt)
{
- // clientId est null si le protocol n'envoie pas le client ID
- if (clnt.clientId != null && this.clientId != null && clnt.clientId == this.clientId)
- return true;
+ // clientId est null si le protocol n'envoie pas le client ID
+ if (clnt.clientId != null && this.clientId != null && clnt.clientId == this.clientId)
+ return true;
return (this.appPort != 0) && (this.appPort == clnt.appPort) && (this.RemoteAddress.Equals(clnt.RemoteAddress));
}
@@ -381,9 +382,9 @@ namespace IvyBus
{
Ivy.traceProtocol(Resources.IvyClient, Resources.Connected + RemoteAddress + ":" + RemotePort);
- Ivy.traceProtocol(Resources.IvyClient,"Thread started");
+ Ivy.traceProtocol(Resources.IvyClient,Resources.ThreadStart);
- bool running = true;
+ bool running = true;
while ( running && (stream != null) )
{
try
@@ -397,20 +398,20 @@ namespace IvyBus
else
{
Ivy.traceProtocol(Resources.IvyClient, Resources.BadReceive);
- running = false;
+ running = false;
break;
}
}
catch ( ObjectDisposedException ex )
{
- Ivy.traceError(Resources.IvyClient, Resources.SocketClosed + ex.Message);
+ Ivy.traceError(Resources.IvyClient, Resources.SocketClosed + ex.Message);
running = false;
break;
}
catch (IvyException ie)
{
- Ivy.traceError(Resources.IvyClient, Resources.SocketClosed + ie.Message);
- running = false;
+ Ivy.traceError(Resources.IvyClient, Resources.SocketClosed + ie.Message);
+ running = false;
break;
}
catch (SocketException se)
@@ -423,7 +424,7 @@ namespace IvyBus
{
if ( ex.InnerException is SocketException )
{
- Ivy.traceProtocol(Resources.IvyClient, Resources.SocketClosed );
+ Ivy.traceProtocol(Resources.IvyClient, Resources.SocketClosed );
}
else
@@ -435,49 +436,49 @@ namespace IvyBus
}
}
Ivy.traceProtocol(Resources.IvyClient,Resources.Disconnected + appName);
- Ivy.traceProtocol(Resources.IvyClient,"Thread stopped");
+ Ivy.traceProtocol(Resources.IvyClient,Resources.ThreadStop);
// invokes the Disconnected applicationListeners
- bus.OnClientDisconnected(new IvyEventArgs(this,0, string.Empty ));
+ bus.OnClientDisconnected(new IvyEventArgs(this,0, string.Empty ));
// first, I'm not a first class IvyClient any more
- if (stream != null)
- {
- stream.Close();
- stream = null;
- }
+ if (stream != null)
+ {
+ stream.Close();
+ stream = null;
+ }
bus.removeClient(this);
}
- void IvyProtocol.Close()
- {
- // never call in this side
- }
- bool IvyProtocol.ReceiveMsg()
- {
- // nerver call in this side
- return false;
- }
- void IvyProtocol.TokenDie(int id, string arg)
+ void IvyProtocol.Close()
+ {
+ // never call in this side
+ }
+ bool IvyProtocol.ReceiveMsg()
+ {
+ // nerver call in this side
+ return false;
+ }
+ void IvyProtocol.TokenDie(int id, string arg)
{
Ivy.traceProtocol(Resources.IvyClient, Resources.DieReceive + appName + Resources.Reason + arg);
// invokes the die applicationListeners
- IvyDieEventArgs ev = new IvyDieEventArgs(this, id, arg);
- bus.OnDie(ev);
- // first, I'm not a first class IvyClient any more
- bus.removeClient(this);
- // makes the bus die
+ IvyDieEventArgs ev = new IvyDieEventArgs(this, id, arg);
+ bus.OnDie(ev);
+ // first, I'm not a first class IvyClient any more
+ bus.removeClient(this);
+ // makes the bus die
bus.Stop();
close(false);
- if (ev.ForceExit)
+ if (ev.ForceExit)
#if (PocketPC)
- System.Windows.Forms.Application.Exit();
+ System.Windows.Forms.Application.Exit();
#else
System.Environment.Exit(0);
#endif
}
- void IvyProtocol.TokenBye(int err, string arg)
+ void IvyProtocol.TokenBye(int err, string arg)
{
// the peer quits
- Ivy.traceProtocol(Resources.IvyClient, Resources.ByeReceive + appName + Resources.Reason + arg);
+ Ivy.traceProtocol(Resources.IvyClient, Resources.ByeReceive + appName + Resources.Reason + arg);
// first, I'm not a first class IvyClient any more
//bus.removeClient(this); // this is done in the receive thread terminaison!!
// invokes the disconnect applicationListeners
@@ -485,125 +486,125 @@ namespace IvyBus
close(false); // will fire disconnected
}
- void IvyProtocol.TokenAddBinding(BindingType type, int id, string expression)
+ void IvyProtocol.TokenAddBinding(BindingType type, int id, string expression)
{
- if (type == BindingType.RegularExpression && !bus.CheckRegexp(expression))
- {
- bus.OnClientFilterBinding(new IvyEventArgs(this, id, expression ));
- return;
- }
- IvyBindingBase bind = null;
- try
- {
- switch (type)
- {
- case BindingType.RegularExpression:
- bind = new IvyBindingRegexp(expression);
- break;
- case BindingType.Simple:
- bind = new IvyBindingSimple(expression);
- break;
- }
- bus.AddBinding(id, this, bind);
+ if (type == BindingType.RegularExpression && !bus.CheckRegexp(expression))
+ {
+ bus.OnClientFilterBinding(new IvyEventArgs(this, id, expression ));
+ return;
+ }
+ IvyBindingBase bind = null;
+ try
+ {
+ switch (type)
+ {
+ case BindingType.RegularExpression:
+ bind = new IvyBindingRegexp(expression);
+ break;
+ case BindingType.Simple:
+ bind = new IvyBindingSimple(expression);
+ break;
+ }
+ bus.AddBinding(id, this, bind);
}
catch (ArgumentException ex)
{
//throw new IvyException("binding expression error " + ex.Message);
- stream.TokenError(7, Resources.BadExpression + " "+ ex.Message);
+ stream.TokenError(7, Resources.BadExpression + " "+ ex.Message);
}
}
- void IvyProtocol.TokenDelBinding(int id)
+ void IvyProtocol.TokenDelBinding(int id)
{
- bus.DelBinding(id, this);
+ bus.DelBinding(id, this);
}
- void IvyProtocol.TokenMsg(int id, string[] args)
+ void IvyProtocol.TokenMsg(int id, string[] args)
{
- bus.OnMessage(new IvyMessageEventArgs(this, id, args));
+ bus.OnMessage(new IvyMessageEventArgs(this, id, args));
}
- void IvyProtocol.TokenError(int id, string arg)
+ void IvyProtocol.TokenError(int id, string arg)
{
- bus.OnError(new IvyEventArgs(this, id, arg));
+ bus.OnError(new IvyEventArgs(this, id, arg));
Ivy.traceError(Resources.IvyClient,Resources.ErrorReceive + id + " " + arg);
}
-
- void IvyProtocol.TokenEndRegexp()
- {
- bus.OnClientConnected(new IvyEventArgs(this, 0, string.Empty));
- /*
- * the peer is perhaps not ready to handle this message
- * an assymetric processing should be written
- */
- SendReadyToPeer();
- }
-
- private void SendReadyToPeer()
- {
- lock (readyToSendLock)
- {
- readyToSend++;
- if (bus.ReadyMessage != null && readyToSend == 2)
- {
- bus.SendMsgToClient(this, bus.ReadyMessage);
- }
- }
- }
- void IvyProtocol.TokenStartRegexp(int id, string arg)
- {
- //bool bindingToSend = appPort == 0;
+
+ void IvyProtocol.TokenEndRegexp()
+ {
+ bus.OnClientConnected(new IvyEventArgs(this, 0, string.Empty));
+ /*
+ * the peer is perhaps not ready to handle this message
+ * an assymetric processing should be written
+ */
+ SendReadyToPeer();
+ }
+
+ private void SendReadyToPeer()
+ {
+ lock (readyToSendLock)
+ {
+ readyToSend++;
+ if (bus.ReadyMessage != null && readyToSend == 2)
+ {
+ bus.SendMsgToClient(this, bus.ReadyMessage);
+ }
+ }
+ }
+ void IvyProtocol.TokenStartRegexp(int id, string arg)
+ {
+ //bool bindingToSend = appPort == 0;
appName = arg;
appPort = id;
- IvyClient target = this;
- IvyClient client = bus.checkConnected(this);
- if (client != null)
- {
- // Dilemma choose the rigth client to close
- // the symetric processing will try to close each other
- // only one side may be closed
- //Console.WriteLine(" should close {0} this local {1} rem {2} other local {3} rem {4}", this.appName, this.localPort, this.remotePort, client.localPort, client.remotePort);
- if (Math.Max(client.localPort, client.remotePort) > Math.Max( this.localPort, this.remotePort ))
- {
- target = client;
- //Console.WriteLine("choose {0} other ports {1},{2}", target.appName, target.localPort, target.remotePort);
- }
- else
- {
- target = this;
- //Console.WriteLine("choose {0} this ports {1},{2}", target.appName, target.remotePort, target.localPort);
- }
- bus.removeClient(target);
- target.close(false);
- //throw new IvyException(Resources.ConcurrentConnect + " " + appName + " " + clientId);
-
- }
- //if ( bindingToSend && target != this)
- // SendBindings();
-
+ IvyClient target = this;
+ IvyClient client = bus.checkConnected(this);
+ if (client != null)
+ {
+ // Dilemma choose the rigth client to close
+ // the symetric processing will try to close each other
+ // only one side may be closed
+ //Console.WriteLine(" should close {0} this local {1} rem {2} other local {3} rem {4}", this.appName, this.localPort, this.remotePort, client.localPort, client.remotePort);
+ if (Math.Max(client.localPort, client.remotePort) > Math.Max( this.localPort, this.remotePort ))
+ {
+ target = client;
+ //Console.WriteLine("choose {0} other ports {1},{2}", target.appName, target.localPort, target.remotePort);
+ }
+ else
+ {
+ target = this;
+ //Console.WriteLine("choose {0} this ports {1},{2}", target.appName, target.remotePort, target.localPort);
+ }
+ bus.removeClient(target);
+ target.close(false);
+ //throw new IvyException(Resources.ConcurrentConnect + " " + appName + " " + clientId);
+
+ }
+ //if ( bindingToSend && target != this)
+ // SendBindings();
+
}
- void IvyProtocol.TokenDirectMsg(int id, string arg)
+ void IvyProtocol.TokenDirectMsg(int id, string arg)
{
- bus.OnDirectMessage(new IvyEventArgs(this,id,arg));
+ bus.OnDirectMessage(new IvyEventArgs(this,id,arg));
}
- void IvyProtocol.TokenPing(int id, string arg)
+ void IvyProtocol.TokenPing(int id, string arg)
{
// I receive a ping. I can answer a pong.
Ivy.traceProtocol(Resources.IvyClient, Resources.PingReceive + appName + " : " + arg );
stream.TokenPong(id,arg);
}
- void IvyProtocol.TokenPong(int id, string arg)
+ void IvyProtocol.TokenPong(int id, string arg)
{
- Ivy.traceProtocol(Resources.IvyClient, Resources.PingReceive + appName + " : " + arg);
+ Ivy.traceProtocol(Resources.IvyClient, Resources.PingReceive + appName + " : " + arg);
}
- /// <summary>
- /// return full Application name pair
- /// </summary>
+ /// <summary>
+ /// return full Application name pair
+ /// </summary>
public override String ToString()
{
return Resources.IvyClient+ " " + bus.appName + ":" + appName;
@@ -621,58 +622,58 @@ namespace IvyBus
try
{
Thread.Sleep(PINGTIMEOUT);
- int id = (int)DateTime.Now.Ticks;
+ int id = (int)DateTime.Now.Ticks;
stream.TokenPing( id, Resources.PingerThreadMessage);
}
catch (ThreadAbortException ie)
{
- Ivy.traceError(Resources.IvyClient,Resources.PingerThreadKilled + ie.Message);
+ Ivy.traceError(Resources.IvyClient,Resources.PingerThreadKilled + ie.Message);
}
}
Ivy.traceProtocol(Resources.IvyClient,Resources.PingerThreadStopped);
}
- /// <summary>
- /// stop the pinger Thread
- /// </summary>
+ /// <summary>
+ /// stop the pinger Thread
+ /// </summary>
public virtual void StopPinging()
{
isPinging = false;
//pingerThread.Interrupt();
- pingerThread.Abort();
- }
-
- #region IDisposable Members
-
- //Implement IDisposable.
- 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.
-
- }
-
- // Use C# destructor syntax for finalization code.
- ~IvyClient()
- {
- // Simply call Dispose(false).
- Dispose(false);
- }
-
- #endregion
- }
+ pingerThread.Abort();
+ }
+
+ #region IDisposable Members
+
+ //Implement IDisposable.
+ 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.
+
+ }
+
+ // Use C# destructor syntax for finalization code.
+ ~IvyClient()
+ {
+ // Simply call Dispose(false).
+ Dispose(false);
+ }
+
+ #endregion
+ }
} \ No newline at end of file
diff --git a/Ivy/IvyUDPStream.cs b/Ivy/IvyUDPStream.cs
index 0e64381..91ef854 100644
--- a/Ivy/IvyUDPStream.cs
+++ b/Ivy/IvyUDPStream.cs
@@ -40,7 +40,7 @@ namespace IvyBus
internal void receiveMsg(out IPEndPoint remote, out int version, out int port, out string appId, out string appName)
{
int len;
- IPEndPoint remoteEP = new IPEndPoint(IPAddress.Any, 0);
+ IPEndPoint remoteEP = new IPEndPoint(socket.AddressFamily == AddressFamily.InterNetworkV6 ? IPAddress.IPv6Any : IPAddress.Any, 0);
EndPoint tempRemoteEP = (EndPoint)remoteEP;
remoteEP = null;
len = socket.ReceiveFrom(buffer, ref tempRemoteEP);
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;
/// <summary> IvyWatcher, A private Class for the Ivy rendezvous
/// </summary>
@@ -26,13 +26,14 @@ namespace IvyBus
/// that the broadcast is done using the same socket, which is not a good
/// thing.
/// </remarks>
- 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;
/// <summary> creates an Ivy watcher
/// </summary>
@@ -42,38 +43,46 @@ namespace IvyBus
/// </param>
/// <param name='port'>the port number
/// </param>
- 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
}
/// <summary>
- /// the behaviour of each thread watching the UDP socket.
+ /// the behaviour of each thread watching the UDP socket.
/// </summary>
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");
}
/// <summary> stops the thread waiting on the broadcast socket
/// </summary>
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");
}
}
/// <summary>
@@ -178,39 +187,39 @@ namespace IvyBus
/// </summary>
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
diff --git a/Ivy/app.config b/Ivy/app.config
index 0df9489..0237982 100644
--- a/Ivy/app.config
+++ b/Ivy/app.config
@@ -7,24 +7,24 @@
</configSections>
<applicationSettings>
<IvyBus.Properties.Settings>
- <setting name="IvyProtocolVersion" serializeAs="String">
- <value>3</value>
- </setting>
- <setting name="IvyPing" serializeAs="String">
- <value>False</value>
- </setting>
- <setting name="IvyDebug" serializeAs="String">
- <value>False</value>
- </setting>
- <setting name="IvyBus" serializeAs="String">
- <value/>
- </setting>
- <setting name="AppName" serializeAs="String">
- <value/>
- </setting>
- <setting name="ReadyMessage" serializeAs="String">
- <value/>
- </setting>
- </IvyBus.Properties.Settings>
+ <setting name="IvyProtocolVersion" serializeAs="String">
+ <value>3</value>
+ </setting>
+ <setting name="IvyPing" serializeAs="String">
+ <value>False</value>
+ </setting>
+ <setting name="IvyDebug" serializeAs="String">
+ <value>False</value>
+ </setting>
+ <setting name="IvyBus" serializeAs="String">
+ <value />
+ </setting>
+ <setting name="AppName" serializeAs="String">
+ <value />
+ </setting>
+ <setting name="ReadyMessage" serializeAs="String">
+ <value />
+ </setting>
+ </IvyBus.Properties.Settings>
</applicationSettings>
<startup/></configuration>
diff --git a/IvyControl/IvyControl.cs b/IvyControl/IvyControl.cs
index 20b43be..47dfd8c 100644
--- a/IvyControl/IvyControl.cs
+++ b/IvyControl/IvyControl.cs
@@ -183,7 +183,18 @@ namespace IvyBus
}
-
+#if (!PocketPC)
+ [Category("Ivy")]
+#endif
+ public bool IpV6
+ {
+ get
+ {
+ return ivy.IpV6;
+ }
+
+ }
+
/// <summary>AppName the application name</summary>
#if (!PocketPC)
diff --git a/IvyControl/IvyDomain.Designer.cs b/IvyControl/IvyDomain.Designer.cs
index 3f89b6a..d66db15 100644
--- a/IvyControl/IvyDomain.Designer.cs
+++ b/IvyControl/IvyDomain.Designer.cs
@@ -28,8 +28,11 @@ namespace IvyBus
/// </summary>
private void InitializeComponent()
{
+ this.components = new System.ComponentModel.Container();
this.label1 = new System.Windows.Forms.Label();
this.ivybus = new System.Windows.Forms.TextBox();
+ this.errorProvider1 = new System.Windows.Forms.ErrorProvider(this.components);
+ ((System.ComponentModel.ISupportInitialize)(this.errorProvider1)).BeginInit();
this.SuspendLayout();
//
// label1
@@ -39,6 +42,7 @@ namespace IvyBus
this.label1.Location = new System.Drawing.Point(0, 5);
this.label1.Name = "label1";
this.label1.Size = new System.Drawing.Size(24, 13);
+ this.label1.TabIndex = 0;
this.label1.Text = "Ivy:";
//
// ivybus
@@ -50,8 +54,13 @@ namespace IvyBus
this.ivybus.Name = "ivybus";
this.ivybus.Size = new System.Drawing.Size(129, 20);
this.ivybus.TabIndex = 2;
- this.ivybus.Validated += new System.EventHandler(this.ivybus_Validated);
this.ivybus.Validating += new System.ComponentModel.CancelEventHandler(this.ivybus_Validating);
+ this.ivybus.Validated += new System.EventHandler(this.ivybus_Validated);
+ //
+ // errorProvider1
+ //
+ this.errorProvider1.BlinkStyle = System.Windows.Forms.ErrorBlinkStyle.AlwaysBlink;
+ this.errorProvider1.ContainerControl = this;
//
// IvyDomain
//
@@ -60,10 +69,9 @@ namespace IvyBus
this.Controls.Add(this.ivybus);
this.Name = "IvyDomain";
this.Size = new System.Drawing.Size(159, 22);
+ ((System.ComponentModel.ISupportInitialize)(this.errorProvider1)).EndInit();
this.ResumeLayout(false);
-#if (!PocketPC)
- this.PerformLayout();
-#endif
+ this.PerformLayout();
}
@@ -71,5 +79,6 @@ namespace IvyBus
private System.Windows.Forms.Label label1;
private System.Windows.Forms.TextBox ivybus;
+ private System.Windows.Forms.ErrorProvider errorProvider1;
}
}
diff --git a/IvyControl/IvyDomain.cs b/IvyControl/IvyDomain.cs
index 36e749a..92b7dbd 100644
--- a/IvyControl/IvyDomain.cs
+++ b/IvyControl/IvyDomain.cs
@@ -49,10 +49,12 @@ namespace IvyBus
private void ivybus_Validating(object sender, CancelEventArgs e)
{
e.Cancel = !Ivy.ValidatingDomain(ivybus.Text);
+ errorProvider1.SetError(this.ivybus, e.Cancel ? "Bad Address":"" );
}
private void ivybus_Validated(object sender, EventArgs e)
{
+ errorProvider1.SetError(this.ivybus, "");
if ( domain != ivybus.Text )
Domain = ivybus.Text;
}
diff --git a/IvyControl/IvyDomain.resx b/IvyControl/IvyDomain.resx
index ff31a6d..e8675cd 100644
--- a/IvyControl/IvyDomain.resx
+++ b/IvyControl/IvyDomain.resx
@@ -117,4 +117,7 @@
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
+ <metadata name="errorProvider1.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
+ <value>17, 17</value>
+ </metadata>
</root> \ No newline at end of file
diff --git a/IvyDaemon/IvyDaemon.cs b/IvyDaemon/IvyDaemon.cs
index 3924df2..9ec2cea 100644
--- a/IvyDaemon/IvyDaemon.cs
+++ b/IvyDaemon/IvyDaemon.cs
@@ -11,7 +11,7 @@ namespace IvyDaemon
using System.Net;
using System.Net.Sockets;
using System.Configuration;
- using System.Diagnostics;
+ using System.Diagnostics;
using IvyBus;
/// <summary> IvyDaemon: simple TCP to Ivy relay.
/// </summary>
@@ -25,7 +25,7 @@ namespace IvyDaemon
private TcpListener serviceSocket;
- private static bool debug = Properties.Settings.Default.IvyDebug;
+ private static bool debug = Properties.Settings.Default.IvyDebug;
private volatile Thread clientThread; // volatile to ensure the quick communication
private Ivy bus;
@@ -161,7 +161,7 @@ namespace IvyDaemon
}
[Conditional("DEBUG")]
- private static void traceDebug(string s)
+ private static void traceDebug(string s)
{
Trace.WriteLineIf(debug, "-->IvyDaemon<-- " + s);
}
diff --git a/IvyProbe/IvyProbe.Designer.cs b/IvyProbe/IvyProbe.Designer.cs
index af5222a..b723029 100644
--- a/IvyProbe/IvyProbe.Designer.cs
+++ b/IvyProbe/IvyProbe.Designer.cs
@@ -136,6 +136,7 @@ namespace IvyProbe
//
// busDomain
//
+ this.busDomain.Domain = "FF02::1:2011";
this.busDomain.Location = new System.Drawing.Point(0, 0);
this.busDomain.Margin = new System.Windows.Forms.Padding(0);
this.busDomain.Name = "busDomain";
@@ -149,20 +150,20 @@ namespace IvyProbe
this.bus.Bindings.Add(this.ivyApplicationBinding1);
this.bus.Culture = new System.Globalization.CultureInfo("en-US");
this.bus.ReadyMessage = "IvyProbeC# ready";
- this.bus.BindingFilter += new System.EventHandler<IvyBus.IvyEventArgs>(this.bus_BindingFilter);
- this.bus.ErrorMessage += new System.EventHandler<IvyBus.IvyEventArgs>(this.bus_ErrorMessage);
- this.bus.DirectMessageReceived += new System.EventHandler<IvyBus.IvyEventArgs>(this.directMessage);
- this.bus.BindingAdd += new System.EventHandler<IvyBus.IvyEventArgs>(this.bus_addBinding);
this.bus.ClientConnected += new System.EventHandler<IvyBus.IvyEventArgs>(this.connect);
this.bus.ClientDisconnected += new System.EventHandler<IvyBus.IvyEventArgs>(this.disconnect);
- this.bus.BindingRemove += new System.EventHandler<IvyBus.IvyEventArgs>(this.bus_removeBinding);
+ this.bus.DirectMessageReceived += new System.EventHandler<IvyBus.IvyEventArgs>(this.directMessage);
this.bus.DieReceived += new System.EventHandler<IvyBus.IvyDieEventArgs>(this.die);
+ this.bus.BindingAdd += new System.EventHandler<IvyBus.IvyEventArgs>(this.bus_addBinding);
+ this.bus.BindingRemove += new System.EventHandler<IvyBus.IvyEventArgs>(this.bus_removeBinding);
+ this.bus.BindingFilter += new System.EventHandler<IvyBus.IvyEventArgs>(this.bus_BindingFilter);
+ this.bus.ErrorMessage += new System.EventHandler<IvyBus.IvyEventArgs>(this.bus_ErrorMessage);
//
// ivyApplicationBinding1
//
this.ivyApplicationBinding1.Arguments.Add("Name");
this.ivyApplicationBinding1.Binding = IvyBus.BindingType.RegularExpression;
- this.ivyApplicationBinding1.Expression = "^%0%(.*)";
+ this.ivyApplicationBinding1.Expression = "(^%0%.*)";
this.ivyApplicationBinding1.Callback += new System.EventHandler<IvyBus.IvyMessageEventArgs>(this.ivyprobe);
//
// IvyProbe
@@ -179,10 +180,9 @@ namespace IvyProbe
this.Controls.Add(this.tbRegexp);
this.Controls.Add(this.label2);
this.Controls.Add(this.label1);
- //this.DoubleBuffered = true;
this.Name = "IvyProbe";
this.Text = "IvyProbe";
- this.FormClosed += new System.Windows.Forms.FormClosedEventHandler(this.IvyProbe_FormClosed);
+ this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.IvyProbe_FormClosing);
this.Load += new System.EventHandler(this.IvyProbe_Load);
((System.ComponentModel.ISupportInitialize)(this.bus)).EndInit();
this.ResumeLayout(false);
diff --git a/IvyProbe/IvyProbe.cs b/IvyProbe/IvyProbe.cs
index 270dbd8..a066447 100644
--- a/IvyProbe/IvyProbe.cs
+++ b/IvyProbe/IvyProbe.cs
@@ -152,11 +152,6 @@ namespace IvyProbe
bus.ivy.Start(busDomain.Domain);
}
- private void IvyProbe_FormClosed(object sender, FormClosedEventArgs e)
- {
- bus.ivy.Stop();
- }
-
private void IvyProbe_Load(object sender, EventArgs e)
{
bus.ivy.Start(busDomain.Domain);
@@ -168,6 +163,12 @@ namespace IvyProbe
receive(sender, e);
}
+ private void IvyProbe_FormClosing(object sender, FormClosingEventArgs e)
+ {
+ bus.ivy.Stop();
+ e.Cancel = false;
+ }
+
}
} \ No newline at end of file
diff --git a/IvyProbe/Properties/Settings.Designer.cs b/IvyProbe/Properties/Settings.Designer.cs
index b907809..c5ef330 100644
--- a/IvyProbe/Properties/Settings.Designer.cs
+++ b/IvyProbe/Properties/Settings.Designer.cs
@@ -25,7 +25,7 @@ namespace IvyProbe.Properties {
[global::System.Configuration.ApplicationScopedSettingAttribute()]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
- [global::System.Configuration.DefaultSettingValueAttribute("")]
+ [global::System.Configuration.DefaultSettingValueAttribute("ff05::1")]
public string IvyBus {
get {
return ((string)(this["IvyBus"]));
diff --git a/IvyProbe/Properties/Settings.settings b/IvyProbe/Properties/Settings.settings
index 421d8f2..44eacd4 100644
--- a/IvyProbe/Properties/Settings.settings
+++ b/IvyProbe/Properties/Settings.settings
@@ -3,7 +3,7 @@
<Profiles />
<Settings>
<Setting Name="IvyBus" Type="System.String" Scope="Application">
- <Value Profile="(Default)" />
+ <Value Profile="(Default)">ff05::1</Value>
</Setting>
</Settings>
</SettingsFile> \ No newline at end of file
diff --git a/IvyProbe/app.config b/IvyProbe/app.config
index e9c8b0c..a4b7d37 100644
--- a/IvyProbe/app.config
+++ b/IvyProbe/app.config
@@ -8,7 +8,7 @@
<applicationSettings>
<IvyProbe.Properties.Settings>
<setting name="IvyBus" serializeAs="String">
- <value />
+ <value>ff05::1</value>
</setting>
</IvyProbe.Properties.Settings>
</applicationSettings>