summaryrefslogtreecommitdiff
path: root/Ivy/IvyPPC/Ivy.cs
diff options
context:
space:
mode:
Diffstat (limited to 'Ivy/IvyPPC/Ivy.cs')
-rw-r--r--Ivy/IvyPPC/Ivy.cs1183
1 files changed, 0 insertions, 1183 deletions
diff --git a/Ivy/IvyPPC/Ivy.cs b/Ivy/IvyPPC/Ivy.cs
deleted file mode 100644
index 1c38396..0000000
--- a/Ivy/IvyPPC/Ivy.cs
+++ /dev/null
@@ -1,1183 +0,0 @@
-/// François-Régis Colin
-/// http://www.tls.cena.fr/products/ivy/
-/// *
-/// (C) CENA
-/// *
-///
-
-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.ComponentModel;
- using System.Diagnostics;
-
-#if (!PocketPC)
- using System.ComponentModel.Design;
-#endif
-// using System.Drawing.Design;
-
-
- /// <summary> The Main bus Class
- /// </summary>
- ///
-#if (!PocketPC)
- // Show this property in the property grid.
- [ToolboxItemFilter("System.Windows.Forms.Form", ToolboxItemFilterType.Allow)]
- [Description("IVY Main API")]
-#endif
- [DesignerCategory("Component")]
- public class Ivy : System.ComponentModel.Component, ISupportInitialize
- {
- /* Event */
- /// <summary>fires when a new client connect to the bus</summary>
- public event EventHandler<IvyEventArgs> ClientConnected;
- /// <summary>fires when a client discconnect from the bus</summary>
- public event EventHandler<IvyEventArgs> ClientDisconnected;
- /// <summary>fires when a client receive a direct message from another client</summary>
- public event EventHandler<IvyEventArgs> DirectMessageReceived;
- /// <summary>fires when somebody ask for killing every client on the bus</summary>
- public event EventHandler<IvyDieEventArgs> DieReceived;
- /// <summary>fires when a client receive a add binding from another client</summary>
- public event EventHandler<IvyEventArgs> BindingAdd;
- /// <summary>fires when a client receive a remove binding from another client</summary>
- public event EventHandler<IvyEventArgs> BindingRemove;
- /// <summary>fires when a client receive a binding from another client and it as been filtered </summary>
- public event EventHandler<IvyEventArgs> BindingFilter;
- /// <summary>fires when a client receive a remove binding from another client</summary>
- public event EventHandler<IvyEventArgs> ErrorMessage;
-
-#if (!PocketPC)
- [Bindable(true)]
- [Category("Ivy")]
-#endif
- [DefaultValue(false)]
- public static bool DebugProtocol
- {
- get
- {
- return debugProtocol;
- }
- set
- {
- debugProtocol = value;
- }
-
- }
-#if (!PocketPC)
- [Category("Ivy")]
-#endif
- public CultureInfo Culture
- {
- get
- {
- return culture;
- }
- set
- {
- culture = value;
- }
-
- }
-
- /// <summary>IvyClients accesses the list of the connected clients</summary>
-#if (!PocketPC)
- [Browsable(false)]
-#endif
- public List<IvyClient> IvyClients
- {
- get
- {
- return clients;
- }
-
- }
-
- /// <summary>AppName the application name</summary>
-
-#if (!PocketPC)
- [Category("Ivy")]
- [Bindable(true)]
-#endif
- [DefaultValue(null)]
- public string AppName
- {
- set
- {
- appName = value;
- }
- get
- {
- return appName;
- }
-
- }
- /// <summary>AppId the Application Unique ID</summary>
-
-#if (!PocketPC)
- [Browsable(false)]
-#endif
- public string AppId
- {
- get
- {
- return applicationUniqueId;
- }
-
- }
- /// <summary>AppPriority the Application Priority: the clients list is sorted against priority</summary>
-#if (!PocketPC)
- [Category("Ivy")]
-#endif
- [DefaultValue(DEFAULT_PRIORITY)]
- public ushort AppPriority
- {
- set
- {
- applicationPriority = value;
- lock (clients)
- {
- foreach (IvyClient client in clients)
- {
- client.stream.TokenApplicationId(applicationPriority, AppId);
- }
- }
-
- }
- get
- {
- return applicationPriority;
- }
-
- }
-
-#if (!PocketPC)
- [Browsable(false)]
-#endif
- public int ProtocolVersion
- {
- get
- {
- return protocolVersion;
- }
-
- }
-
- /// <summary>IsRunning is the bus Started and connected ?</summary>
-
-#if (!PocketPC)
- [Browsable(false)]
-#endif
- public bool IsRunning
- {
- get
- {
- return !stopped;
- }
-
- }
- ///<summary>SentMessageClasses the first word token of sent messages
- ///<remarks> optimise the parsing process when sending messages </remarks>
- ///</summary>
-#if (!PocketPC)
- [Category("Ivy")]
-
- [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
- // sinon bug System.String constructor not found !
- [Editor("System.Windows.Forms.Design.StringCollectionEditor, System.Design", "System.Drawing.Design.UITypeEditor, System.Drawing")]
-#endif
- public List<string> SentMessageFilter
- {
- get
- {
- return sent_messageFilter;
- }
- }
- /// <summary>ReadyMessage message send when Application receive all the regexp at the connection of the client</summary>
-
-#if (!PocketPC)
- [Bindable(true)]
- [Category("Ivy")]
-#endif
- [DefaultValue(null)]
- public string ReadyMessage
- {
- get { return ready_message; }
- set { ready_message = value; }
- }
-
-
-
-
-#if (PocketPC)
-#if (!PocketPC)
- [Category("Ivy")]
-#endif
- [DefaultValue(null)]
- public System.Windows.Forms.ContainerControl ContainerControl
- {
- get { return parentControl; }
- set
- {
- parentControl = value;
- }
- }
-#endif
-#if (!PocketPC)
- [Category("Ivy")]
- [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
-#endif
- public List<IvyApplicationBinding> Bindings
- {
- get { return app_bindings; }
- }
-
- 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 DEFAULT_PORT = 2010;
- // client default priority
- internal const ushort DEFAULT_PRIORITY = 100;
- /// the domain for the UDP rendez vous
- private static readonly string DEFAULT_DOMAIN = "127.255.255.255:" + DEFAULT_PORT;
- internal int protocolVersion = 3;
- private static bool debugProtocol; // false by default runtime
- private static ushort serial; /* an unique ID for each regexp */ // 0 by default runtime
- private MyTcpListener app;
- private List<IvyWatcher> watchers;
- private volatile Thread serverThread; // to ensure quick communication of the end
-
- internal Dictionary<int, IvyApplicationBinding> bindings;
- //TODO should be remove samve as above
- private List<IvyApplicationBinding> app_bindings;
- private List<IvyClient> clients;
- private List<string> sent_messageFilter;
- private bool stopped = true;
- internal ushort applicationPort; /* Application port number */
- internal IPAddress applicationHost; /* Application host number */
- internal string applicationUniqueId; /* identifier Application unique timestamp-ipaddress-port */
- internal ushort applicationPriority = DEFAULT_PRIORITY;
- private string ready_message;
- private CultureInfo culture = new CultureInfo("en-us");
- // for synchronous event
-#if (PocketPC)
- private System.Windows.Forms.ContainerControl parentControl;
-#else
- private readonly SynchronizationContext syncContext;
-#endif
-
-
- /// <summary>
- /// Initializes a new instance of the <see cref="T:Ivy"/> class.
- /// </summary>
- public Ivy()
- {
-#if (!PocketPC)
- syncContext = SynchronizationContext.Current;
-#endif
- clients = new List<IvyClient>();
- bindings = new Dictionary<int, IvyApplicationBinding>();
- app_bindings = new List<IvyApplicationBinding>();
- sent_messageFilter = new List<string>();
-#if (!PocketPC)
- debugProtocol = Properties.Settings.Default.IvyDebug;
- protocolVersion = Properties.Settings.Default.IvyProtocolVersion;
-#endif
- // get binding from Attribute IvyBinding
- //TODO Autobinding attribute
-#if (PocketPC)
- if (parentControl != null)
- BindAttibute(parentControl);
-#endif
- Assembly assembly = Assembly.GetCallingAssembly();
- if ( assembly != this.GetType().Assembly )
- BindAttibute(assembly);
- }
- public Ivy(IContainer container)
- : this()
- {
- container.Add(this);
- // get binding from Attribute IvyBinding
- //TODO Autobinding attribute
- Assembly assembly = Assembly.GetCallingAssembly();
- if (assembly != this.GetType().Assembly)
- BindAttibute(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 rdy_message)
- : this()
- {
- appName = name;
- ready_message = rdy_message;
- // get binding from Attribute IvyBinding
- //TODO Autobinding attribute
- Assembly assembly = Assembly.GetCallingAssembly();
- if (assembly != this.GetType().Assembly)
- BindAttibute(assembly);
- }
-
- protected override void Dispose(bool disposing)
- {
- try
- {
- if (disposing)
- {
- Stop();
- }
- }
- finally
- {
- base.Dispose(disposing);
- }
- }
-
- // Autobinding on static method
- public void BindAttibute(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.GetExpression(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;
-#else
- handler = (EventHandler<IvyMessageEventArgs>)Delegate.CreateDelegate(typeof(EventHandler<IvyMessageEventArgs>), m);
-#endif
- BindMsg(attr.GetExpression(null), handler);
- }
- }
- }
- // Autobinding on instance method
- public void BindAttibute(object obj)
- {
- if (obj == null) return;
- Type type = obj.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("Ivy", "BindAttibute " + attr.GetExpression(obj) + "' to Method " + m.Name);
- EventHandler<IvyMessageEventArgs> handler;
-#if (PocketPC)
- handler = null; // TODO
-#else
- handler = (EventHandler<IvyMessageEventArgs>)Delegate.CreateDelegate(typeof(EventHandler<IvyMessageEventArgs>), obj, m);
-#endif
- BindMsg(attr.GetExpression(obj), handler);
- }
- }
-
- }
- // Autobinding on IvyBindingAttribute method
- public void BindAttibute(Assembly assy)
- {
- foreach (Type typ in assy.GetTypes())
- {
- BindAttibute(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 = GetLocalIP();
- applicationPort = (ushort)((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>();
-
- 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.Run));
- serverThread.Name = "Ivy Tcp Server Thread";
- stopped = false;
- serverThread.Start();
-
-#if (PocketPC )
- Ivy.traceProtocol("Ivy", "Threading start in progress...");
- Thread.Sleep(100);
-#else
- // Wait for readyness
- while ( serverThread.ThreadState != System.Threading.ThreadState.Running || !app.IsActive())
- {
- Ivy.traceError("BindAttibute", " Ivy Threading start in progress..." );
- Thread.Sleep( 100 );
- }
-#endif
- // 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();
- }
- }
- /* a small private method for debbugging purposes */
-
- public static string Domains(string toparse)
- {
- string domainbus = GetDomain(toparse);
- StringBuilder s = new StringBuilder("broadcasting on ");
- Ivy.Domain[] d = parseDomains(domainbus);
- for (int index = 0; index < d.Length; index++)
- {
- s.Append(d[index].Domainaddr);
- s.Append(":");
- s.Append(d[index].Port);
- s.Append(" ");
- }
- return s.ToString();
- }
-
- 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("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;
- copyClient = new IvyClient[clients.Count];
- lock (clients)
- {
- clients.CopyTo(copyClient, 0);
- }
- 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("Ivy", "IOexception Stop " + e.Message);
- }
- Ivy.traceProtocol("Ivy", "the bus should have stopped so far");
- }
- }
-
-
- /// <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 name='args'>args used in message format
- /// <returns>
- /// the number of messages actually sent
- /// </returns>
- public int SendMsg(string format, params object[] args)
- {
- string msg = string.Format(culture, format, args);
- int count = 0;
- // an alternate implementation would one sender thread per client
- // instead of one for all the clients. It might be a performance issue
- lock (clients)
- {
- // hash message in V4 protocol only
- if (ProtocolVersion == 4)
- IvyBindingSimple.Prepare(msg);
- foreach (IvyClient client in clients)
- {
- count += client.sendMsg(msg);
- }
- }
- return count;
- }
- //
- public ushort BindMsg(IvyApplicationBinding newbind)
- {
- newbind.Key = serial++;
-
- lock (bindings) bindings.Add(newbind.Key, newbind);
- // notifies the other clients this new regexp
- lock (clients)
- {
- foreach (IvyClient c in clients)
- {
- c.stream.TokenAddBinding(newbind.Binding, newbind.Key, newbind.FormatedExpression);
- }
- }
- return newbind.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 Ivy.MessageListener</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.
- /// </remarks>
- //
- public ushort BindMsg(string regexp, EventHandler<IvyMessageEventArgs> callback, params object[] args)
- {
- // creates a new binding (regexp,callback)
- IvyApplicationBinding newbind;
- newbind = new IvyApplicationBinding();
- newbind.Binding = BindingType.Regexp;
- newbind.Expression = regexp;
- newbind.Callback += callback;
- newbind.Args = args;
- 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(ushort id)
- {
- if (!bindings.ContainsKey(id))
- {
- throw new IvyException("client wants to remove an unexistant regexp " + id);
- }
- lock (clients)
- {
- foreach (IvyClient c in clients)
- {
- c.stream.TokenDelBinding(id);
- }
- }
- lock (bindings) bindings.Remove(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 name='callback'>any objects implementing the EventHandler<IvyMessageEventArgs>
- /// <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();
- newbind.Binding = BindingType.Simple;
- newbind.Expression = expression;
- newbind.Callback += callback;
- newbind.Args = args;
- 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)
- {
- List<IvyClient> v = GetClientsByName(target);
- for (int i = 0; i < v.Count; i++)
- v[i].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)
- {
- List<IvyClient> v = GetClientsByName(target);
- for (int i = 0; i < v.Count; i++)
- v[i].stream.TokenPing(message);
- return v.Count;
- }
-#if (PocketPC)
- internal virtual void FireEvent(EventHandler<IvyEventArgs> ev, IvyEventArgs e)
- {
- if (ev != null)
- {
- if (parentControl != null)
- {
- parentControl.Invoke(ev, this, e);
- }
- else
- ev(this, e);
- }
- }
-#else
- internal virtual void FireEvent(EventHandler<IvyEventArgs> ev, IvyEventArgs e)
- {
- if (ev != null)
- {
- if (syncContext != null)
- {
- SendOrPostCallback update = delegate(object state)
- {
- IvyEventArgs args = (IvyEventArgs)state;
- ev(this, args);
- };
- syncContext.Post(update, e);
- }
- else
- ev(this, e);
- }
- }
-
-#endif
- 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 ex)
- {
- // 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 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);
- }
- }
-
-#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);
- }
- }
-#endif
- internal void OnMessage(IvyMessageEventArgs e)
- {
- IvyApplicationBinding bind = bindings[e.Id];
-
- if (bind == null)
- {
- throw new IvyException("(callCallback) Not regexp matching id " + e.Id);
- }
-#if(PocketPC)
- bind.Firevent(parentControl, e);
-#else
- bind.Firevent(syncContext, e);
-#endif
- }
-
- /*
- * removes a client from the list
- */
- internal void removeClient(IvyClient c)
- {
- lock (clients)
- {
- clients.Remove(c);
- }
- }
-
-
- /// <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 List<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 v;
- }
-
- /////////////////////////////////////////////////////////////////:
- //
- // Protected methods
- //
- /////////////////////////////////////////////////////////////////:
-
- internal void addClient(Socket socket, string appname)
- {
- if (stopped)
- return;
- IvyClient client = new IvyClient(this, socket, appname);
- lock (clients)
- {
- clients.Add(client);
- }
- client.SendBindings();
- }
-
-
- public static IPAddress GetLocalIP()
- {
- 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;
- }
-
- 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);
- }
-#else
- if (domainbus == null || domainbus.Length == 0 )
- {
- domainbus = Environment.GetEnvironmentVariable("IVYBUS");
- }
-
- if (domainbus == null || domainbus.Length == 0)
- {
- domainbus = Properties.Settings.Default.IvyBus;
- }
-#endif
- if (domainbus == null || domainbus.Length == 0)
- domainbus = DEFAULT_DOMAIN;
- 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.
- */
- //TODO bug multiple instance Reco car en 127.0.0.1
- internal bool checkConnected(IvyClient clnt)
- {
- if (clnt.AppPort == 0)
- return false;
- lock (clients)
- {
- foreach (IvyClient client in clients)
- {
- if (clnt != client && client.sameClient(clnt))
- return true;
- }
- }
- return false;
- }
-
- /*
- * the service socket thread reader main loop
- */
- private void Run()
- {
- Ivy.traceProtocol("Ivy", "Ivy service Thread started");
- bool running = true;
- while (running)
- {
- try
- {
- Socket socket = app.AcceptSocket();
- if (stopped)
- break;
- // early disconnexion
- addClient(socket, "Unkown(waiting for name reception)"); // the peer called me
- }
- catch (IOException e)
- {
- Ivy.traceError("Ivy","Ivy server socket reader caught an exception: " + e.Message);
- }
- catch (SocketException e)
- {
- Ivy.traceError("Ivy","my server socket has been closed " + e.Message);
- running = false;
- }
- }
- Ivy.traceProtocol("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;
- }
-
- }
- public virtual int Port
- {
- get
- {
- return port;
- }
-
- }
- private string domainaddr;
- private int port;
- public Domain(string net)
- {
- this.domainaddr = getDomain(net);
- this.port = 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
- {
- net += ".255.255.255";
- Regex exp = new Regex("^(\\d+\\.\\d+\\.\\d+\\.\\d+).*");
- net = exp.Replace(net, "$1");
- }
- catch (ArgumentException e)
- {
- Ivy.traceError("Ivy","Bad broascat addr " + net + "error " + e.Message);
- return null;
- }
- return net;
- }
-
- public static int getPort(string net)
- {
- if (net == null) return Ivy.DEFAULT_PORT;
- int sep_index = net.LastIndexOf(":");
- int port = (sep_index == -1) ? Ivy.DEFAULT_PORT : Int32.Parse(net.Substring(sep_index + 1));
- return port;
- }
- }
-
-
- public static bool ValidatingDomain(string p)
- {
- // domain if of the form ip1[:port][,ip2[:port]] with ip of the form n1.n2.n3.n4
- return Regex.IsMatch(p, @"\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}:\d+");
- }
-
- #region ISupportInitialize Members
-
- public void BeginInit()
- {
-
- }
-
- public void EndInit()
- {
- // TODO ugly should be added directly the bindings Dictionary !
- foreach (IvyApplicationBinding bind in app_bindings)
- {
- BindMsg(bind);
- }
- }
-
- #endregion
-
- }
-} \ No newline at end of file