summaryrefslogtreecommitdiff
path: root/CSharp/Ivy/IvyPPC
diff options
context:
space:
mode:
authorfcolin2007-02-01 09:55:44 +0000
committerfcolin2007-02-01 09:55:44 +0000
commita9dd85dff37fdaaa9995658acf0b8e9e455ddb86 (patch)
treec7976d2be3b6cc111d9c83cc2742c5b237836928 /CSharp/Ivy/IvyPPC
parentb61cb9d5b95a94abf550d718e6bf717ec007b97e (diff)
downloadivy-csharp-a9dd85dff37fdaaa9995658acf0b8e9e455ddb86.zip
ivy-csharp-a9dd85dff37fdaaa9995658acf0b8e9e455ddb86.tar.gz
ivy-csharp-a9dd85dff37fdaaa9995658acf0b8e9e455ddb86.tar.bz2
ivy-csharp-a9dd85dff37fdaaa9995658acf0b8e9e455ddb86.tar.xz
Utilisateur : Fcolin Date : 9/02/06 Heure : 16:24 Archivé dans $/CSharp/Ivy/IvyPPC Commentaire: (vss 54)
Diffstat (limited to 'CSharp/Ivy/IvyPPC')
-rw-r--r--CSharp/Ivy/IvyPPC/Ivy.cs1377
1 files 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;
-
- /// <summary> The Main bus Class
- /// </summary>
+
+ /// <summary> The Main bus Class
+ /// </summary>
///
#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 */
- /// <summary>fires when a new client connect to the bus</summary>
- /// <param name='appcb'>A callback handling the notification of connexions and
- /// disconnections, may be null
- ///
- /// </param>
- public event ClientConnectedHandler ClientConnected;
- /// <summary>fires when a client discconnect from the bus</summary>
- public event ClientDisconnectedHandler ClientDisconnected;
- /// <summary>fires when a client receive a direct message from another client</summary>
- public event DirectMessageHandler DirectMessageReceived;
- /// <summary>fires when somebody ask for killing every client on the bus</summary>
- public event DieHandler dieReceived;
- /// <summary>fires when a client receive a add binding from another client</summary>
- public event ClientAddBindingHandler BindingAdd;
- /// <summary>fires when a client receive a remove binding from another client</summary>
+ 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 */
+ /// <summary>fires when a new client connect to the bus</summary>
+ /// <param name='appcb'>A callback handling the notification of connexions and
+ /// disconnections, may be null
+ ///
+ /// </param>
+ public event ClientConnectedHandler ClientConnected;
+ /// <summary>fires when a client discconnect from the bus</summary>
+ public event ClientDisconnectedHandler ClientDisconnected;
+ /// <summary>fires when a client receive a direct message from another client</summary>
+ public event DirectMessageHandler DirectMessageReceived;
+ /// <summary>fires when somebody ask for killing every client on the bus</summary>
+ public event DieHandler dieReceived;
+ /// <summary>fires when a client receive a add binding from another client</summary>
+ public event ClientAddBindingHandler BindingAdd;
+ /// <summary>fires when a client receive a remove binding from another client</summary>
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
}
- /// <summary>IvyClients accesses the list of the connected clients</summary>
-
+ /// <summary>IvyClients accesses the list of the connected clients</summary>
+
#if (!PocketPC)
[Browsable(false)]
#endif
public List<IvyClient> IvyClients
- {
- get
- {
- return clients;
- }
-
- }
- /// <summary>ClientNames accesses the name list of the connected clients</summary
+ {
+ get
+ {
+ return clients;
+ }
+
+ }
+ /// <summary>ClientNames accesses the name list of the connected clients</summary
private string ClientNames
- {
- get
- {
+ {
+ get
+ {
StringBuilder s = new StringBuilder();
s.Append(appName);
- s.Append( " clients are: " );
- lock( clients )
- {
- foreach (IvyClient client in clients )
- {
+ s.Append(" clients are: ");
+ lock (clients)
+ {
+ foreach (IvyClient client in clients)
+ {
s.Append(client.ApplicationName);
- s.Append( " " );
- }
- }
- return s.ToString();
- }
-
- }
- /// <summary>AppName the application name</summary>
-
+ s.Append(" ");
+ }
+ }
+ return s.ToString();
+ }
+
+ }
+ /// <summary>AppName the application name</summary>
+
#if (!PocketPC)
[Category("Ivy")]
[Bindable(true)]
[DefaultValue(null)]
#endif
public string AppName
- {
+ {
set
- {
- appName = value;
- }
- get
- {
- return appName;
- }
-
- }
+ {
+ appName = value;
+ }
+ get
+ {
+ return appName;
+ }
+
+ }
/// <summary>AppId the Application Unique ID</summary>
-
+
#if (!PocketPC)
[Browsable(false)]
#endif
public string AppId
- {
- get
- {
- return applicationUniqueId;
- }
-
- }
+ {
+ get
+ {
+ return applicationUniqueId;
+ }
+
+ }
/// <summary>AppPriority the Application Priority: the clients list is sorted against priority</summary>
-
+
#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
}
}
- ///<summary>SentMessageClasses the first word token of sent messages
- ///<remarks> optimise the parsing process when sending messages </remarks>
- ///</summary>
-
+ ///<summary>SentMessageClasses the first word token of sent messages
+ ///<remarks> optimise the parsing process when sending messages </remarks>
+ ///</summary>
+
#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;
+ }
+
+ }
/// <summary>ReadyMessage message send when Application receive all the regexp at the connection of the client</summary>
-
+
#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<IvyWatcher> watchers;
- private volatile Thread serverThread; // to ensure quick communication of the end
+ private MyTcpListener app;
+ private List<IvyWatcher> 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<int,ApplicationBinding> bindings;
- private List<IvyClient> clients;
- private string[] sent_messageClasses = null;
- private bool stopped = false;
- internal ushort applicationPort; /* Application port number */
+ internal Dictionary<int, ApplicationBinding> bindings;
+ private List<IvyClient> 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<IvyClient>();
@@ -310,47 +332,50 @@ namespace IvyBus
protocolVersion = Properties.Settings.Default.IvyProtocolVersion;
#endif
}
- /// <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("(.*)",new Ivy.MessageHandler(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 message):this()
- {
+ /// <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("(.*)",new Ivy.MessageHandler(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 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);
}
}
-
- }
- /// <summary> connects the Ivy bus to a domain or list of domains.
- /// </summary>
- /// <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>
- /// <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>
- public void start(string domainbus)
- {
+
+ }
+ /// <summary> connects the Ivy bus to a domain or list of domains.
+ /// </summary>
+ /// <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>
+ /// <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>
+ 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<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;
+ 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 )
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;
- }
-
- /// <summary> disconnects from the Ivy bus
- /// </summary>
- 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");
- }
- }
-
-
- /// <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
- /// </param>
- /// <returns>the number of messages actually sent
- ///
- /// </returns>
- 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;
+ }
+
+ /// <summary> disconnects from the Ivy bus
+ /// </summary>
+ 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");
+ }
+ }
+
+
+ /// <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
+ /// </param>
+ /// <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
@@ -571,25 +598,25 @@ namespace IvyBus
}
}
return count;
- }
-
- /// <summary> Subscribes to a regular expression.
- /// </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 Ivy.MessageListener
- /// </param>
- /// <returns>the id of the regular expression
- ///
- /// </returns>
- //
- // for compatibility raison with old IVY
+ }
+
+ /// <summary> Subscribes to a regular expression.
+ /// </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 Ivy.MessageListener
+ /// </param>
+ /// <returns>the id of the regular expression
+ ///
+ /// </returns>
+ //
+ // 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;
- }
-
- /// <summary> unsubscribes a regular expression
- /// </summary>
- /// <param name='id'>the id of the regular expression, returned when it was bound
- ///
- /// </param>
+ }
+ }
+ return newbind.key;
+ }
+
+ /// <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);
- }
- ApplicationBinding bind = (ApplicationBinding) bindings[id];
- lock( clients )
- {
- foreach (IvyClient c in clients )
- {
- c.stream.TokenDelBinding(id);
- }
- }
- lock( bindings ) bindings.Remove( id );
- }
-
- /// <summary> unsubscribes a regular expression
- /// </summary>
- /// <returns>a boolean, true if the regexp existed, false otherwise or
- /// whenever an exception occured during unbinding
- /// </returns>
- /// <param name='re'>the string for the regular expression
- ///
- /// </param>
- 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);
+ }
+
+ /// <summary> unsubscribes a regular expression
+ /// </summary>
+ /// <returns>a boolean, true if the regexp existed, false otherwise or
+ /// whenever an exception occured during unbinding
+ /// </returns>
+ /// <param name='re'>the string for the regular expression
+ ///
+ /// </param>
+ 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;
+ }
- /// <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 Ivy.MessageListener
- /// </param>
- /// <returns>the id of the regular expression
- ///
- /// </returns>
-
- 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++;
+ /// <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 Ivy.MessageListener
+ /// </param>
+ /// <returns>the id of the regular expression
+ ///
+ /// </returns>
+
+ 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<IvyClient> 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<IvyClient> 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);
- }
- }
-
-
- /// <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>
- public List<IvyClient> getIvyClientsByName(string name)
- {
+
+ /*
+ * 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>
+ public List<IvyClient> getIvyClientsByName(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);
- }
- 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, @"^\^(?<token>[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, @"^\^(?<token>[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;
+ }
}