From 5395c909bc0d38728eed6096cb71362411921485 Mon Sep 17 00:00:00 2001 From: fcolin Date: Thu, 1 Feb 2007 09:44:09 +0000 Subject: Utilisateur : Fcolin Date : 23/06/06 Heure : 11:12 Archivé dans $/CSharp/Ivy/Ivy Commentaire: (vss 66) --- CSharp/Ivy/Ivy/Ivy.cs | 269 ++++++++++++++++++++++++++++---------------------- 1 file changed, 149 insertions(+), 120 deletions(-) (limited to 'CSharp/Ivy') diff --git a/CSharp/Ivy/Ivy/Ivy.cs b/CSharp/Ivy/Ivy/Ivy.cs index a64acb8..5f29976 100644 --- a/CSharp/Ivy/Ivy/Ivy.cs +++ b/CSharp/Ivy/Ivy/Ivy.cs @@ -24,6 +24,11 @@ namespace IvyBus using System.ComponentModel; using System.Diagnostics; + using System.ComponentModel; + using System.ComponentModel.Design; + using System.Drawing.Design; + + /// The Main bus Class /// /// @@ -33,7 +38,7 @@ namespace IvyBus [Description("IVY Main API")] #endif [DesignerCategory("Component")] - public class Ivy : System.ComponentModel.Component, ISupportInitialize + public class Ivy : System.ComponentModel.Component, ISupportInitialize { /* Event */ /// fires when a new client connect to the bus @@ -192,18 +197,18 @@ namespace IvyBus #if (!PocketPC) [Category("Ivy")] #endif - [DefaultValue(null)] - public StringCollection SentMessageClasses + [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)] + // sinon bug System.String constructor not found ! + [Editor( + "System.Windows.Forms.Design.StringCollectionEditor, System.Design, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a", + "System.Drawing.Design.UITypeEditor,System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" + )] + public StringCollection SentMessageFilter { get { - return sent_messageClasses; - } - set - { - sent_messageClasses = value; + return sent_messageFilter; } - } /// ReadyMessage message send when Application receive all the regexp at the connection of the client @@ -229,6 +234,34 @@ namespace IvyBus syncControl = value; } } +#if (!PocketPC) + [Category("Ivy")] +#endif + + [DefaultValue(null)] + [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)] + [Editor(typeof(IvyBindingCollectionEditor), typeof(UITypeEditor))] + public List Bindings + { + get { return app_bindings; } + //set { app_bindings = value; } + } + //create a collection editor class + + private class IvyBindingCollectionEditor : CollectionEditor + { + public IvyBindingCollectionEditor(Type type) + : base(type) + { + } + + //Over ride the function which will return the STYLES collection + protected override System.Type[] CreateNewItemTypes() + { + return new Type[] { typeof(IvyApplicationBinding) }; + } + } + internal class MyTcpListener : TcpListener { public MyTcpListener(IPAddress address, int port) @@ -240,7 +273,6 @@ namespace IvyBus 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 @@ -250,25 +282,17 @@ namespace IvyBus /// 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 debug; // false by deflaut runtime + private static bool debug; // false by default runtime private static ushort serial; /* an unique ID for each regexp */ // 0 by default runtime private MyTcpListener app; private List watchers; private volatile Thread serverThread; // to ensure quick communication of the end - internal enum BindingType { BindRegexp, BindSimple }; - internal struct ApplicationBinding /* Self Applications bindings */ - { - internal BindingType type; - internal ushort key; - internal EventHandler callback; - internal string expression; - internal object[] args; - } - - internal Dictionary bindings; + internal Dictionary bindings; + //TODO should be remove samve as above + private List app_bindings; private List clients; - private StringCollection sent_messageClasses; + private StringCollection sent_messageFilter; private bool stopped = true; internal ushort applicationPort; /* Application port number */ internal IPAddress applicationHost; /* Application host number */ @@ -283,7 +307,9 @@ namespace IvyBus public Ivy() { clients = new List(); - bindings = new Dictionary(); + bindings = new Dictionary(); + app_bindings = new List(); + sent_messageFilter = new StringCollection(); #if (!PocketPC ) debug = Properties.Settings.Default.IvyDebug; protocolVersion = Properties.Settings.Default.IvyProtocolVersion; @@ -341,6 +367,7 @@ namespace IvyBus base.Dispose(disposing); } } + // Autobinding on static method public void AutoBinding(Type type) { @@ -570,6 +597,9 @@ namespace IvyBus // 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); @@ -577,7 +607,22 @@ namespace IvyBus } 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.Expression); + } + } + return newbind.Key; + } /// Subscribes to a regular expression. /// /// @@ -605,22 +650,13 @@ namespace IvyBus public ushort BindMsg(string regexp, EventHandler callback, params object[] args) { // creates a new binding (regexp,callback) - ApplicationBinding newbind; - newbind.type = BindingType.BindRegexp; - newbind.key = serial++; - newbind.expression = regexp; - newbind.callback = callback; - newbind.args = args; - 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); - } - } - return newbind.key; + IvyApplicationBinding newbind; + newbind = new IvyApplicationBinding(); + newbind.Binding = BindingType.Regexp; + newbind.Expression = regexp; + newbind.Callback += callback; + newbind.Args = args; + return BindMsg(newbind); } /// unsubscribes a regular expression @@ -634,7 +670,6 @@ namespace IvyBus { throw new IvyException("client wants to remove an unexistant regexp " + id); } - //ApplicationBinding bind = (ApplicationBinding)bindings[id]; lock (clients) { foreach (IvyClient c in clients) @@ -655,13 +690,13 @@ namespace IvyBus /// public bool UnbindMsg(string re) { - foreach (ApplicationBinding bind in bindings.Values) + foreach (IvyApplicationBinding bind in bindings.Values) { - if (bind.expression == re) + if (bind.Expression == re) { try { - UnbindMsg(bind.key); + UnbindMsg(bind.Key); } catch (IvyException) { @@ -684,7 +719,7 @@ namespace IvyBus /// /// a regular expression, groups are done with parenthesis /// - /// any objects implementing the Ivy.MessageListener + /// any objects implementing the EventHandler /// /// the id of the regular expression /// @@ -693,22 +728,13 @@ namespace IvyBus public int BindSimpleMsg(string expression, EventHandler callback, params object[] args) { // creates a new binding (regexp,callback) - ApplicationBinding newbind; - newbind.type = BindingType.BindSimple; - newbind.key = serial++; - newbind.expression = expression; - newbind.callback = callback; - newbind.args = args; - 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); - } - } - return newbind.key; + IvyApplicationBinding newbind; + newbind = new IvyApplicationBinding(); + newbind.Binding = BindingType.Simple; + newbind.Expression = expression; + newbind.Callback += callback; + newbind.Args = args; + return BindMsg(newbind); } public int Die(string target, string message) { @@ -735,86 +761,77 @@ namespace IvyBus return true; else return false; } - internal virtual void OnDirectMessage(IvyEventArgs e) + internal virtual void FireEvent(EventHandler ev, IvyEventArgs e) { - if (DirectMessageReceived != null) + if (ev != null) { if (IsSynchronous()) - syncControl.Invoke(DirectMessageReceived, this, e ); - else DirectMessageReceived(this, e); + syncControl.Invoke(ev, this, e); + else ev(this, e); } } + internal virtual void OnDirectMessage(IvyEventArgs e) + { + // Copy to a temporary variable to be thread-safe. + EventHandler temp = DirectMessageReceived; + FireEvent(temp,e); + } internal virtual void OnClientConnected(IvyEventArgs e) { - if (ClientConnected != null) - { - if (IsSynchronous()) - syncControl.Invoke(ClientConnected, this, e ); - else ClientConnected(this,e); - } - + // Copy to a temporary variable to be thread-safe. + EventHandler temp = ClientConnected; + FireEvent(temp,e); } internal virtual void OnClientDisconnected(IvyEventArgs e) { - if (ClientDisconnected != null) + // Copy to a temporary variable to be thread-safe. + EventHandler temp = ClientDisconnected; + try { - try - { - if (IsSynchronous()) - syncControl.Invoke(ClientDisconnected, this, e ); - else ClientDisconnected(this,e); - } - catch (ObjectDisposedException ) - { - // protect terminaison - } + FireEvent(temp,e); } + catch (ObjectDisposedException) + { + // protect terminaison + } + } internal virtual void OnClientAddBinding(IvyEventArgs e) { - if (BindingAdd != null) - { - if (IsSynchronous()) - syncControl.Invoke(BindingAdd, this, e ); - else BindingAdd(this, e); - } + // Copy to a temporary variable to be thread-safe. + EventHandler temp = BindingAdd; + FireEvent(temp,e); } internal virtual void OnClientRemoveBinding(IvyEventArgs e) { - if (BindingRemove != null) - { - if (IsSynchronous()) - syncControl.Invoke(BindingRemove, this, e ); - else BindingRemove(this, e); - } + // Copy to a temporary variable to be thread-safe. + EventHandler temp = BindingRemove; + FireEvent(temp,e); } internal virtual void OnClientFilterBinding(IvyEventArgs e) { - if (BindingFilter != null) - { - if (IsSynchronous()) - syncControl.Invoke(BindingFilter, this, e); - else BindingFilter(this, e); - } + // Copy to a temporary variable to be thread-safe. + EventHandler temp = BindingFilter; + FireEvent(temp,e); } - internal virtual void OnDie(IvyDieEventArgs e) + internal virtual void OnError(IvyEventArgs e) { - if (DieReceived != null) - { - if (IsSynchronous()) - syncControl.Invoke(DieReceived, this, e ); - else DieReceived(this, e); - } + // Copy to a temporary variable to be thread-safe. + EventHandler temp = ErrorMessage; + FireEvent(temp, e); } - internal virtual void OnError(IvyEventArgs e) + internal virtual void OnDie(IvyDieEventArgs e) { - if (ErrorMessage != null) + // Copy to a temporary variable to be thread-safe. + EventHandler temp = DieReceived; + if (temp != null) { if (IsSynchronous()) - syncControl.Invoke(ErrorMessage, this, e ); - else ErrorMessage(this, e); + syncControl.Invoke(temp, this, e ); + else temp(this, e); } } + /* * removes a client from the list @@ -860,16 +877,24 @@ namespace IvyBus } } - internal void FireCallback(IvyMessageEventArgs e) + internal void OnMessage(IvyMessageEventArgs e) { - ApplicationBinding bind = bindings[e.Id]; - if (bind.callback == null) + IvyApplicationBinding bind = bindings[e.Id]; + + if (bind == null) { throw new IvyException("(callCallback) Not regexp matching id " + e.Id); } + //// Safely invoke an event: + EventHandler temp = bind.CallbackHandler; + + if (temp == null) + { + throw new IvyException("(callCallback) Not callback for id " + e.Id); + } if (IsSynchronous()) - syncControl.Invoke(bind.callback, this, e ); - else bind.callback(this, e); + syncControl.Invoke(temp, this, e ); + else temp(this, e); } public static IPAddress GetLocalIP() @@ -934,13 +959,13 @@ namespace IvyBus // Attention Bug // ClockStop ClockStart & ^Clock(Start|Pause) // should Stop to the first parent - if ((sent_messageClasses != null) && exp.StartsWith("^")) + if ((sent_messageFilter.Count != 0) && exp.StartsWith("^")) { regexp_ok = false; // extract first word from regexp... string token = Regex.Replace(exp, @"^\^(?[a-zA-Z_0-9-]+).*", @"${token}"); - foreach (string exp_class in sent_messageClasses) + foreach (string exp_class in sent_messageFilter) { if (exp_class.StartsWith(token)) return true; @@ -1087,8 +1112,12 @@ namespace IvyBus { if (syncControl != null) AutoBinding(syncControl); + // TODO ugly should be added directly the bindings Dictionary ! + foreach (IvyApplicationBinding bind in app_bindings) + BindMsg(bind); } #endregion + } } \ No newline at end of file -- cgit v1.1