From a9dd85dff37fdaaa9995658acf0b8e9e455ddb86 Mon Sep 17 00:00:00 2001 From: fcolin Date: Thu, 1 Feb 2007 09:55:44 +0000 Subject: Utilisateur : Fcolin Date : 9/02/06 Heure : 16:24 Archivé dans $/CSharp/Ivy/IvyPPC Commentaire: (vss 54) --- CSharp/Ivy/IvyPPC/Ivy.cs | 1377 ++++++++++++++++++++++++---------------------- 1 file changed, 708 insertions(+), 669 deletions(-) diff --git a/CSharp/Ivy/IvyPPC/Ivy.cs b/CSharp/Ivy/IvyPPC/Ivy.cs index f6eef1a..6ddc0f4 100644 --- a/CSharp/Ivy/IvyPPC/Ivy.cs +++ b/CSharp/Ivy/IvyPPC/Ivy.cs @@ -7,25 +7,25 @@ namespace IvyBus { - using System; - using System.IO; - using System.Collections; + 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.Windows.Forms; - using System.Globalization; - using System.Text.RegularExpressions; + using System.Net.Sockets; + using System.Threading; + using System.Configuration; + using System.Windows.Forms; + using System.Globalization; + using System.Text.RegularExpressions; using System.Text; using System.Reflection; using System.ComponentModel; using System.Diagnostics; - - /// The Main bus Class - /// + + /// The Main bus Class + /// /// #if (!PocketPC) @@ -34,36 +34,36 @@ namespace IvyBus [Description("IVY Main API")] #endif public class Ivy : System.ComponentModel.Component - { + { /* return value for Die Event */ public enum ApplicationExit { FORCE_EXIT, DONT_EXIT }; /* Event handler */ - public delegate void DirectMessageHandler (IvyClient app, int id, string arg ); - public delegate void ClientConnectedHandler (IvyClient app); - public delegate void ClientDisconnectedHandler (IvyClient app); + public delegate void DirectMessageHandler(IvyClient app, int id, string arg); + public delegate void ClientConnectedHandler(IvyClient app); + public delegate void ClientDisconnectedHandler(IvyClient app); public delegate ApplicationExit DieHandler(IvyClient app, int id, string arg); - public delegate void ClientAddBindingHandler (IvyClient app, string arg ); - public delegate void ClientRemoveBindingHandler (IvyClient app, string arg ); - - public delegate void MessageHandler ( IvyClient app, string[] args ); - - - /* Event */ - /// fires when a new client connect to the bus - /// A callback handling the notification of connexions and - /// disconnections, may be null - /// - /// - public event ClientConnectedHandler ClientConnected; - /// fires when a client discconnect from the bus - public event ClientDisconnectedHandler ClientDisconnected; - /// fires when a client receive a direct message from another client - public event DirectMessageHandler DirectMessageReceived; - /// fires when somebody ask for killing every client on the bus - public event DieHandler dieReceived; - /// fires when a client receive a add binding from another client - public event ClientAddBindingHandler BindingAdd; - /// fires when a client receive a remove binding from another client + public delegate void ClientAddBindingHandler(IvyClient app, string arg); + public delegate void ClientRemoveBindingHandler(IvyClient app, string arg); + + public delegate void MessageHandler(IvyClient app, string[] args); + + + /* Event */ + /// fires when a new client connect to the bus + /// A callback handling the notification of connexions and + /// disconnections, may be null + /// + /// + public event ClientConnectedHandler ClientConnected; + /// fires when a client discconnect from the bus + public event ClientDisconnectedHandler ClientDisconnected; + /// fires when a client receive a direct message from another client + public event DirectMessageHandler DirectMessageReceived; + /// fires when somebody ask for killing every client on the bus + public event DieHandler dieReceived; + /// fires when a client receive a add binding from another client + public event ClientAddBindingHandler BindingAdd; + /// fires when a client receive a remove binding from another client public event ClientRemoveBindingHandler BindingRemove; #if (!PocketPC) @@ -71,7 +71,7 @@ namespace IvyBus [Bindable(true)] [DefaultValue(false)] #endif - public static bool VerboseDebug + public static bool VerboseDebug { get { @@ -100,98 +100,98 @@ namespace IvyBus } - /// IvyClients accesses the list of the connected clients - + /// IvyClients accesses the list of the connected clients + #if (!PocketPC) [Browsable(false)] #endif public List IvyClients - { - get - { - return clients; - } - - } - /// ClientNames accesses the name list of the connected clientsClientNames accesses the name list of the connected clientsAppName the application name - + s.Append(" "); + } + } + return s.ToString(); + } + + } + /// AppName the application name + #if (!PocketPC) [Category("Ivy")] [Bindable(true)] [DefaultValue(null)] #endif public string AppName - { + { set - { - appName = value; - } - get - { - return appName; - } - - } + { + appName = value; + } + get + { + return appName; + } + + } /// AppId the Application Unique ID - + #if (!PocketPC) [Browsable(false)] #endif public string AppId - { - get - { - return applicationUniqueId; - } - - } + { + get + { + return applicationUniqueId; + } + + } /// AppPriority the Application Priority: the clients list is sorted against priority - + #if (!PocketPC) [Category("Ivy")] [DefaultValue(DEFAULT_PRIORITY)] #endif public ushort AppPriority - { - set - { - applicationPriority = value; - lock ( clients ) - { - foreach (IvyClient client in clients ) - { - client.stream.TokenApplicationId(applicationPriority, AppId); - } - } - - } - get - { - return applicationPriority; - } - - } - + { + set + { + applicationPriority = value; + lock (clients) + { + foreach (IvyClient client in clients) + { + client.stream.TokenApplicationId(applicationPriority, AppId); + } + } + + } + get + { + return applicationPriority; + } + + } + #if (!PocketPC) [Browsable(false)] #endif @@ -203,28 +203,28 @@ namespace IvyBus } } - ///SentMessageClasses the first word token of sent messages - /// optimise the parsing process when sending messages - /// - + ///SentMessageClasses the first word token of sent messages + /// optimise the parsing process when sending messages + /// + #if (!PocketPC) [Category("Ivy")] [DefaultValue(null)] #endif public string[] SentMessageClasses - { - get - { - return sent_messageClasses; - } - set - { - sent_messageClasses = value; - } - - } + { + get + { + return sent_messageClasses; + } + set + { + sent_messageClasses = value; + } + + } /// ReadyMessage message send when Application receive all the regexp at the connection of the client - + #if (!PocketPC) [Category("Ivy")] [Bindable(true)] @@ -246,52 +246,74 @@ namespace IvyBus set { syncControl = value; - if ( syncControl != null ) + if (syncControl != null) AutoBinding(syncControl); } } - 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 class MyTcpListener : TcpListener + { + public MyTcpListener(IPAddress address, int port) + : base(address, port) + { + } + public bool IsActive() + { + return this.Active; + } + } +#if PocketPC + internal class Createdelegate + { + object eventtarget; + MethodInfo mymethod; + object [] methodparams = new Object[2]; + + public void Invoke(object sender, System.EventArgs e) + { + methodparams[1] = e; + mymethod.Invoke(eventtarget, methodparams); + } + + public Createdelegate(MethodInfo mi, object eventTarget, object eventObject) + { + eventtarget = eventTarget; + mymethod = mi; + methodparams[0] = eventObject; + methodparams[1] = null; + } + } +#endif + /// the name of the application on the bus internal string appName; - /// the port for the UDP rendez vous, if none is supplied + /// the port for the UDP rendez vous, if none is supplied internal const ushort DEFAULT_PORT = 2010; - // client default priority + // 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; - private const string libVersion = "2.0.0"; + /// the domain for the UDP rendez vous + private static readonly string DEFAULT_DOMAIN = "127.255.255.255:" + DEFAULT_PORT; + private const string libVersion = "2.0.0"; internal int protocolVersion = 3; private static bool debug = false; private static ushort serial = 0; /* an unique ID for each regexp */ - private MyTcpListener app; - private List watchers; - private volatile Thread serverThread; // to ensure quick communication of the end + 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 enum BindingType { BindRegexp, BindSimple }; + internal struct ApplicationBinding /* Self Applications bindings */ + { + internal BindingType type; internal ushort key; - internal MessageHandler callback; - internal string expression; - internal object[] args; - } + internal MessageHandler callback; + internal string expression; + internal object[] args; + } - internal Dictionary bindings; - private List clients; - private string[] sent_messageClasses = null; - private bool stopped = false; - internal ushort applicationPort; /* Application port number */ + internal Dictionary bindings; + private List clients; + private string[] sent_messageClasses = null; + private bool stopped = false; + 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; @@ -299,8 +321,8 @@ namespace IvyBus private CultureInfo culture = new CultureInfo("en-us"); // for synchronous event private Control syncControl = null; - - + + public Ivy() { clients = new List(); @@ -310,47 +332,50 @@ namespace IvyBus protocolVersion = Properties.Settings.Default.IvyProtocolVersion; #endif } - /// Readies the structures for the software bus connexion. - /// - /// This sample shows how to start working with Ivy. - /// - /// Ivy bus = new Ivy("Dummy agent","ready"); - /// bus.bindMsg("(.*)",new Ivy.MessageHandler(myMessageListener)); - /// bus.start(null); - /// - /// How to send & receive: - /// the Ivy agent A performs b.bindMsg("^Hello (*)",cb); - /// the Ivy agent B performs b2.sendMsg("Hello world"); - /// a thread in A will run the callback cb with its second argument set - /// to a array of string, with one single element, "world" - /// - /// - /// the real work begin in the start() method - /// - /// - /// The name of your Ivy agent on the software bus - /// - /// The hellow message you will send once ready - /// - public Ivy(string name, string message):this() - { + /// Readies the structures for the software bus connexion. + /// + /// This sample shows how to start working with Ivy. + /// + /// Ivy bus = new Ivy("Dummy agent","ready"); + /// bus.bindMsg("(.*)",new Ivy.MessageHandler(myMessageListener)); + /// bus.start(null); + /// + /// How to send & receive: + /// the Ivy agent A performs b.bindMsg("^Hello (*)",cb); + /// the Ivy agent B performs b2.sendMsg("Hello world"); + /// a thread in A will run the callback cb with its second argument set + /// to a array of string, with one single element, "world" + /// + /// + /// the real work begin in the start() method + /// + /// + /// The name of your Ivy agent on the software bus + /// + /// The hellow message you will send once ready + /// + public Ivy(string name, string message) + : this() + { appName = name; - ready_message = message; - } - public Ivy(Control sync): this() + ready_message = message; + } + public Ivy(Control sync) + : this() { syncControl = sync; } - public Ivy(string name, string message, Control sync) :this( name, message ) - { - syncControl = sync; - } - + public Ivy(string name, string message, Control sync) + : this(name, message) + { + syncControl = sync; + } + // Autobinding on static method public void AutoBinding(Type type) { //Get instance of the IvyBindingAttribute. - foreach (MethodInfo m in type.GetMethods( BindingFlags.Static | BindingFlags.NonPublic)) + foreach (MethodInfo m in type.GetMethods(BindingFlags.Static | BindingFlags.NonPublic)) { foreach (IvyBindingAttribute attr in Attribute.GetCustomAttributes(m, typeof(IvyBindingAttribute))) { @@ -358,7 +383,9 @@ namespace IvyBus Debug.WriteLine("IvyBinding '" + attr.GetExpression(null) + "' to Method " + m.Name); MessageHandler handler; #if (PocketPC) - handler = null; // TODO + //Createdelegate mydlg = new Createdelegate(m, null, EventArgs.Empty); + //bindMsg(attr.GetExpression(null), mydlg); + handler = null; #else handler = (MessageHandler)Delegate.CreateDelegate(typeof(MessageHandler), m); #endif @@ -370,7 +397,7 @@ namespace IvyBus public void AutoBinding(object obj) { Type type = obj.GetType(); - //Get instance of the IvyBindingAttribute. + //Get instance of the IvyBindingAttribute. foreach (MethodInfo m in type.GetMethods(BindingFlags.Instance | BindingFlags.NonPublic)) { foreach (IvyBindingAttribute attr in Attribute.GetCustomAttributes(m, typeof(IvyBindingAttribute))) @@ -386,57 +413,57 @@ namespace IvyBus bindMsg(attr.GetExpression(obj), handler); } } - - } - /// connects the Ivy bus to a domain or list of domains. - /// - /// - /// 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. - /// - /// 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. - /// * - /// - /// - public void start(string domainbus) - { + + } + /// connects the Ivy bus to a domain or list of domains. + /// + /// + /// 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. + /// + /// 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. + /// * + /// + /// + public void start(string domainbus) + { domainbus = getDomain(domainbus); - try - { + try + { 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("{0}-{1}-{2}", - DateTime.Now.Ticks / TimeSpan.TicksPerMillisecond, - applicationHost.ToString().Replace(".",""), - applicationPort ); - - } - catch (IOException e) - { - throw new IvyException("can't open TCP service socket " + e); - } + DateTime.Now.Ticks / TimeSpan.TicksPerMillisecond, + applicationHost.ToString().Replace(".", ""), + applicationPort); + + } + catch (IOException e) + { + throw new IvyException("can't open TCP service socket " + e); + } traceDebug("lib: " + libVersion + " protocol: " + ProtocolVersion + " TCP service open on port " + applicationPort); - watchers = new List(); - - 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; + watchers = new List(); + + 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 ) traceDebug(" Ivy Threading start in progress..."); Thread.Sleep(100); @@ -449,117 +476,117 @@ namespace IvyBus } #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()); + 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 string domains(string toparse) - { - StringBuilder s = new StringBuilder("broadcasting on "); - Ivy.Domain[] d = parseDomains(toparse); - for (int index = 0; index < d.Length; index++) - { + } + } + /* a small private method for debbugging purposes */ + + public string domains(string toparse) + { + StringBuilder s = new StringBuilder("broadcasting on "); + Ivy.Domain[] d = parseDomains(toparse); + 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 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(IvyWatcher.getDomain(st[i]), IvyWatcher.getPort(st[i])); - } - return d; - } - - /// disconnects from the Ivy bus - /// - public void stop() - { - lock(this) - { - if (stopped) - return ; - stopped = true; - traceDebug("beginning stopping the bus"); - try - { - // stopping the serverThread - if (serverThread != null) - { - app.Stop(); - serverThread.Join(); - 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) - { - traceDebug("IOexception Stop " + e.Message); - } - traceDebug("the bus should have stopped so far"); - } - } - - - /// Send a formated message to someone on the bus - /// - /// - /// 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. - /// - /// A string message format to build the message - /// args used in message format - /// - /// the number of messages actually sent - /// - /// - public int sendMsg(string format, params object[] args ) - { - string msg = string.Format( culture, format, args ); + s.Append(" "); + } + return s.ToString(); + } + + internal 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(IvyWatcher.getDomain(st[i]), IvyWatcher.getPort(st[i])); + } + return d; + } + + /// disconnects from the Ivy bus + /// + public void stop() + { + lock (this) + { + if (stopped) + return; + stopped = true; + traceDebug("beginning stopping the bus"); + try + { + // stopping the serverThread + if (serverThread != null) + { + app.Stop(); + serverThread.Join(); + 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) + { + traceDebug("IOexception Stop " + e.Message); + } + traceDebug("the bus should have stopped so far"); + } + } + + + /// Send a formated message to someone on the bus + /// + /// + /// 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. + /// + /// A string message format to build the message + /// args used in message format + /// + /// the number of messages actually sent + /// + /// + 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 @@ -571,25 +598,25 @@ namespace IvyBus } } return count; - } - - /// Subscribes to a regular expression. - /// - /// - /// 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. - /// - /// - /// a regular expression, groups are done with parenthesis - /// - /// any objects implementing the Ivy.MessageListener - /// - /// the id of the regular expression - /// - /// - // - // for compatibility raison with old IVY + } + + /// Subscribes to a regular expression. + /// + /// + /// 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. + /// + /// + /// a regular expression, groups are done with parenthesis + /// + /// any objects implementing the Ivy.MessageListener + /// + /// the id of the regular expression + /// + /// + // + // for compatibility raison with old IVY #if OLD_API [Obsolete("Will be removed in next version")] public int bindMsg(string regexp, MessageHandler callback) @@ -597,122 +624,122 @@ namespace IvyBus return bindMsg( regexp, callback, null); } #endif - public int bindMsg(string regexp, MessageHandler callback, params object[] args) - { - // creates a new binding (regexp,callback) - ApplicationBinding newbind; - newbind.type = BindingType.BindRegexp; - newbind.key = serial++; + public int bindMsg(string regexp, MessageHandler 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 ) - { + 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; - } - - /// unsubscribes a regular expression - /// - /// the id of the regular expression, returned when it was bound - /// - /// + } + } + return newbind.key; + } + + /// unsubscribes a regular expression + /// + /// the id of the regular expression, returned when it was bound + /// + /// public void unBindMsg(ushort id) - { - if ( ! bindings.ContainsKey( id ) ) - { - throw new IvyException("client wants to remove an unexistant regexp " + id); - } - ApplicationBinding bind = (ApplicationBinding) bindings[id]; - lock( clients ) - { - foreach (IvyClient c in clients ) - { - c.stream.TokenDelBinding(id); - } - } - lock( bindings ) bindings.Remove( id ); - } - - /// unsubscribes a regular expression - /// - /// a boolean, true if the regexp existed, false otherwise or - /// whenever an exception occured during unbinding - /// - /// the string for the regular expression - /// - /// - public bool unBindMsg(string re) - { - foreach (ApplicationBinding bind in bindings.Values ) - { + { + if (!bindings.ContainsKey(id)) + { + throw new IvyException("client wants to remove an unexistant regexp " + id); + } + ApplicationBinding bind = (ApplicationBinding)bindings[id]; + lock (clients) + { + foreach (IvyClient c in clients) + { + c.stream.TokenDelBinding(id); + } + } + lock (bindings) bindings.Remove(id); + } + + /// unsubscribes a regular expression + /// + /// a boolean, true if the regexp existed, false otherwise or + /// whenever an exception occured during unbinding + /// + /// the string for the regular expression + /// + /// + public bool unBindMsg(string re) + { + foreach (ApplicationBinding bind in bindings.Values) + { if (bind.expression == re) - { - try - { - unBindMsg(bind.key); - } - catch (IvyException) - { - return false; - } - return true; - } - } - return false; - } + { + try + { + unBindMsg(bind.key); + } + catch (IvyException) + { + return false; + } + return true; + } + } + return false; + } - /// Subscribes to a simple expression ( msg ar1 arg2 arg3 etc). - /// - /// - /// 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. - /// - /// - /// a regular expression, groups are done with parenthesis - /// - /// any objects implementing the Ivy.MessageListener - /// - /// the id of the regular expression - /// - /// - - public int bindSimpleMsg(string expression, MessageHandler callback, params object[] args ) - { - // creates a new binding (regexp,callback) - ApplicationBinding newbind; - newbind.type = BindingType.BindSimple; - newbind.key = serial++; + /// Subscribes to a simple expression ( msg ar1 arg2 arg3 etc). + /// + /// + /// 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. + /// + /// + /// a regular expression, groups are done with parenthesis + /// + /// any objects implementing the Ivy.MessageListener + /// + /// the id of the regular expression + /// + /// + + public int bindSimpleMsg(string expression, MessageHandler 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 ) - { + 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; - } - public int Die( string target, string message ) + } + } + return newbind.key; + } + public int Die(string target, string message) { List v = getIvyClientsByName(target); - for (int i = 0; i < v.Count; i++) - v[i].stream.TokenDie(0,message); - return v.Count; + for (int i = 0; i < v.Count; i++) + v[i].stream.TokenDie(0, message); + return v.Count; } - public int Ping( string target, string message) + public int Ping(string target, string message) { List v = getIvyClientsByName(target); for (int i = 0; i < v.Count; i++) @@ -721,128 +748,128 @@ namespace IvyBus } internal bool IsSynchronous() { - if (syncControl != null + if (syncControl != null #if (!PocketPC ) && syncControl.Created #endif - ) - return true; - else return false; +) + return true; + else return false; } internal void FireDirectMessage(IvyClient app, int id, string arg) - { - if ( DirectMessageReceived != null ) + { + if (DirectMessageReceived != null) { if (IsSynchronous()) - syncControl.Invoke( DirectMessageReceived, new object[]{app,id,arg}); - else DirectMessageReceived( app, id, arg); + syncControl.Invoke(DirectMessageReceived, new object[] { app, id, arg }); + else DirectMessageReceived(app, id, arg); } - } - internal void FireClientConnected (IvyClient app) - { - if ( ClientConnected != null ) + } + internal void FireClientConnected(IvyClient app) + { + if (ClientConnected != null) { if (IsSynchronous()) - syncControl.Invoke( ClientConnected, new object[]{app}); - else ClientConnected( app); + syncControl.Invoke(ClientConnected, new object[] { app }); + else ClientConnected(app); } - - } - internal void FireClientDisconnected (IvyClient app) - { - if ( ClientDisconnected != null ) + + } + internal void FireClientDisconnected(IvyClient app) + { + if (ClientDisconnected != null) { if (IsSynchronous()) - syncControl.Invoke( ClientDisconnected, new object[]{app}); - else ClientDisconnected( app); + syncControl.Invoke(ClientDisconnected, new object[] { app }); + else ClientDisconnected(app); } } - internal void FireClientAddBinding (IvyClient app, string regexp) - { - if ( BindingAdd != null ) + internal void FireClientAddBinding(IvyClient app, string regexp) + { + if (BindingAdd != null) { if (IsSynchronous()) - syncControl.Invoke( BindingAdd, new object[]{app,regexp}); - else BindingAdd( app,regexp); + syncControl.Invoke(BindingAdd, new object[] { app, regexp }); + else BindingAdd(app, regexp); } - } - internal void FireClientRemoveBinding (IvyClient app, string regexp) - { - if ( BindingRemove != null ) + } + internal void FireClientRemoveBinding(IvyClient app, string regexp) + { + if (BindingRemove != null) { if (IsSynchronous()) - syncControl.Invoke( BindingRemove, new object[]{app,regexp}); - else BindingRemove( app,regexp); + syncControl.Invoke(BindingRemove, new object[] { app, regexp }); + else BindingRemove(app, regexp); } - } + } internal ApplicationExit FireDie(IvyClient app, int id, string arg) - { - if ( dieReceived != null ) + { + if (dieReceived != null) { if (IsSynchronous()) return (ApplicationExit)syncControl.Invoke(dieReceived, new object[] { app, id, arg }); - else return dieReceived( app, id, arg); + else return dieReceived(app, id, arg); } return ApplicationExit.FORCE_EXIT; - } + } - - /* - * removes a client from the list - */ - internal void removeClient(IvyClient c) - { - lock( clients ) - { - clients.Remove(c); - } - } - - - /// gives a list of IvyClient(s) with the name given in parameter - /// - /// The name of the Ivy agent you're looking for - /// - public List getIvyClientsByName(string name) - { + + /* + * removes a client from the list + */ + internal void removeClient(IvyClient c) + { + lock (clients) + { + clients.Remove(c); + } + } + + + /// gives a list of IvyClient(s) with the name given in parameter + /// + /// The name of the Ivy agent you're looking for + /// + public List getIvyClientsByName(string name) + { List v = new List(); - 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); - } - traceDebug(ClientNames); - } + 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); + } + traceDebug(ClientNames); + } internal void FireCallback(IvyClient client, int key, string[] arg) - { - ApplicationBinding bind = bindings[key]; - if (bind.callback == null) - { - throw new IvyException("(callCallback) Not regexp matching id " + key); - } - if ( IsSynchronous() ) + { + ApplicationBinding bind = bindings[key]; + if (bind.callback == null) + { + throw new IvyException("(callCallback) Not regexp matching id " + key); + } + if (IsSynchronous()) syncControl.Invoke(bind.callback, new object[] { client, arg }); - else bind.callback(client, arg); - } + else bind.callback(client, arg); + } public static IPAddress getLocalIP() { IPAddress returnaddr = null; @@ -856,18 +883,30 @@ namespace IvyBus } return returnaddr; } - - public static string getDomain(string domainbus) - { + + public static string getDomain(string domainbus) + { #if (PocketPC) if (domainbus == null || domainbus.Length == 0) { IPAddress addr = getLocalIP(); //TODO Find Braodcast addr from IP; byte[] bytes = addr.GetAddressBytes(); - bytes[3] = 255; - IPAddress bcast = new IPAddress( bytes ); - domainbus = bcast + ":" + DEFAULT_PORT; + 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 + ":" + DEFAULT_PORT; } #else if (domainbus == null || domainbus.Length == 0 ) @@ -881,118 +920,118 @@ namespace 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_messageClasses != null) && 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) - { - 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. - */ + 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_messageClasses != null) && 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) + { + 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() - { - traceDebug("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) - { - traceDebug("Ivy server socket reader caught an exception: " + e.Message); - } - catch (SocketException e) - { + 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() + { + traceDebug("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) + { + traceDebug("Ivy server socket reader caught an exception: " + e.Message); + } + catch (SocketException e) + { traceDebug("my server socket has been closed " + e.Message); - running = false; - } - } - traceDebug("Ivy service Thread stopped"); - } + running = false; + } + } + traceDebug("Ivy service Thread stopped"); + } [Conditional("DEBUG")] private void traceDebug(string s) - { - Trace.Assert(!debug, "-->ivy<-- " + s); - } - - 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 domainaddr, int port) - { - this.domainaddr = domainaddr; this.port = port; - } - public override string ToString() - { - return domainaddr + ":" + port; - } + { + Trace.Assert(!debug, "-->ivy<-- " + s); + } + + 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 domainaddr, int port) + { + this.domainaddr = domainaddr; this.port = port; + } + public override string ToString() + { + return domainaddr + ":" + port; + } } -- cgit v1.1