From 8d10e8bbd1e19adc7c70e1101dbb69c213c910dd Mon Sep 17 00:00:00 2001 From: fcolin Date: Fri, 22 Aug 2008 16:44:01 +0000 Subject: optimisation for parsing same regular expression from multiple client using fxCop for code beauty fix bug on concurrent connect --- Ivy/Ivy.cs | 556 ++++++++++++++++++++++++++++++++++++++++++------------------- 1 file changed, 386 insertions(+), 170 deletions(-) (limited to 'Ivy/Ivy.cs') diff --git a/Ivy/Ivy.cs b/Ivy/Ivy.cs index 14a3918..bfef8ab 100644 --- a/Ivy/Ivy.cs +++ b/Ivy/Ivy.cs @@ -4,7 +4,7 @@ /// (C) CENA /// * /// - +[assembly: System.CLSCompliant(true)] namespace IvyBus { using System; @@ -21,11 +21,12 @@ namespace IvyBus using System.Text; using System.Reflection; using System.Diagnostics; + using System.Collections.ObjectModel; + using IvyBus.Properties; /// The Main bus Class /// /// - public class Ivy { /* Event */ @@ -36,6 +37,7 @@ namespace IvyBus public event EventHandler BindingAdd; public event EventHandler BindingRemove; public event EventHandler BindingFilter; + public event EventHandler BindingChange; public event EventHandler ErrorMessage; @@ -67,11 +69,11 @@ namespace IvyBus /// IvyClients accesses the list of the connected clients - public List IvyClients + public ReadOnlyCollection IvyClients { get { - return clients; + return new ReadOnlyCollection(clients); } } @@ -100,28 +102,7 @@ namespace IvyBus } } - /// AppPriority the Application Priority: the clients list is sorted against priority - - public ushort AppPriority - { - set - { - applicationPriority = value; - lock (clients) - { - foreach (IvyClient client in clients) - { - client.stream.TokenApplicationId(applicationPriority, AppId); - } - } - - } - get - { - return applicationPriority; - } - - } + public int ProtocolVersion { @@ -146,7 +127,7 @@ namespace IvyBus /// optimise the parsing process when sending messages /// - public List SentMessageFilter + public Collection SentMessageFilter { get { @@ -175,26 +156,37 @@ namespace IvyBus /// the name of the application on the bus internal string appName; /// the port for the UDP rendez vous, if none is supplied - internal const ushort DEFAULT_PORT = 2010; - // client default priority - public const ushort DEFAULT_PRIORITY = 100; + internal const ushort DefaultPort = 2010; /// the domain for the UDP rendez vous - private static readonly string DEFAULT_DOMAIN = "127.255.255.255:" + DEFAULT_PORT; + private static readonly string DefaultDomain = "127.255.255.255:" + DefaultPort; internal int protocolVersion = 3; private static bool debugProtocol; // false by default runtime - private static ushort serial; /* an unique ID for each regexp */ // 0 by default runtime + private static int 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 + private Thread serverThread; // to ensure quick communication of the end + private AutoResetEvent tcplistener_running; + static public Version Version + { + get { return Assembly.GetExecutingAssembly().GetName().Version; } + } + // Class representing Ivy Binding receive from client + internal class IvyClientBinding + { + internal IvyBindingBase binding; + internal Dictionary> client_bindind_ids; + } + // The Application bindings internal Dictionary bindings; + // the clients bindings + private Dictionary client_bindings; private List clients; - private List sent_messageFilter; + private Collection sent_messageFilter; private bool stopped = true; - internal ushort applicationPort; /* Application port number */ + internal int applicationPort; /* Application port number */ internal IPAddress applicationHost; /* Application host number */ internal string applicationUniqueId; /* identifier Application unique timestamp-ipaddress-port */ - internal ushort applicationPriority = DEFAULT_PRIORITY; private string ready_message; private CultureInfo culture = new CultureInfo("en-us"); internal static Encoding ivyEncoding = Encoding.GetEncoding("iso-8859-15"); // ASCII 8 bits iso-8859-2 @@ -212,13 +204,12 @@ namespace IvyBus /// public Ivy() { -#if (!PocketPC) - syncContext = SynchronizationContext.Current; -#endif clients = new List(); bindings = new Dictionary(); - sent_messageFilter = new List(); + client_bindings = new Dictionary(); + sent_messageFilter = new Collection(); #if (!PocketPC) + syncContext = SynchronizationContext.Current; debugProtocol = Properties.Settings.Default.IvyDebug; protocolVersion = Properties.Settings.Default.IvyProtocolVersion; #endif @@ -230,7 +221,7 @@ namespace IvyBus #endif Assembly assembly = Assembly.GetCallingAssembly(); if ( assembly != this.GetType().Assembly ) - BindAttibute(assembly); + BindAttribute(assembly); } /// @@ -256,21 +247,112 @@ namespace IvyBus /// /// The hellow message you will send once ready /// - public Ivy(string name, string rdy_message) + public Ivy(string name, string readyMessage) : this() { appName = name; - ready_message = rdy_message; + this.ready_message = readyMessage; // get binding from Attribute IvyBinding //TODO Autobinding attribute Assembly assembly = Assembly.GetCallingAssembly(); if (assembly != this.GetType().Assembly) - BindAttibute(assembly); + BindAttribute(assembly); } - + internal void AddBinding(int id, IvyClient clnt, IvyBindingBase bindexp) + { + bool change = false; + IvyClientBinding clientbind; + lock (client_bindings) + { + if (client_bindings.ContainsKey(bindexp.Expression)) + { + // check if id exits to remove it + + clientbind = client_bindings[bindexp.Expression]; + + foreach (IvyClientBinding clbind in client_bindings.Values) + { + lock (clbind.client_bindind_ids) + { + if (clbind.client_bindind_ids.ContainsKey(clnt)) + { + if (clbind.client_bindind_ids[clnt].Contains(id)) + { + // remove from old + clbind.client_bindind_ids[clnt].Remove(id); + // add to new later + change = true; //mark to call right handler + break; + } + } + } + + } + + } + else + { + clientbind = new IvyClientBinding(); + clientbind.binding = bindexp; + clientbind.client_bindind_ids = new Dictionary>(); + clientbind.client_bindind_ids[clnt] = new List(); + client_bindings[bindexp.Expression] = clientbind; + + } + } + + lock (clientbind.client_bindind_ids) + { + if (!clientbind.client_bindind_ids.ContainsKey(clnt)) + { + clientbind.client_bindind_ids[clnt] = new List(); + } + clientbind.client_bindind_ids[clnt].Add(id); + } + if (change) + { + OnClientChangeBinding(new IvyEventArgs(clnt, id, bindexp.Expression)); + } + else + { + OnClientAddBinding(new IvyEventArgs(clnt, id, bindexp.Expression)); + } + } + internal void DelBinding(int id, IvyClient clnt) + { + IvyClientBinding clientbind = null; + lock (client_bindings) + { + foreach (IvyClientBinding clbind in client_bindings.Values) + { + lock (clbind.client_bindind_ids) + { + if (clbind.client_bindind_ids.ContainsKey(clnt)) + { + clbind.client_bindind_ids[clnt].Remove(id); + clientbind = clbind; + break; + } + } + } + if (clientbind != null) + { + lock (clientbind.client_bindind_ids) + { + if (clientbind.client_bindind_ids.Count == 0) + { + client_bindings.Remove(clientbind.binding.Expression); + } + } + } + } + if (clientbind != null ) + OnClientRemoveBinding(new IvyEventArgs(clnt, id, clientbind.binding.Expression)); + + } // Autobinding on static method - public void BindAttibute(Type type) + public void BindAttribute(Type type) { if (type == null) return; //Get instance of the IvyBindingAttribute. @@ -279,7 +361,7 @@ namespace IvyBus foreach (IvyBindingAttribute attr in Attribute.GetCustomAttributes(m, typeof(IvyBindingAttribute))) { //TODO check paramater type MessageHandler - Debug.WriteLine("IvyBinding '" + attr.GetExpression(null) + "' to Method " + m.Name); + Debug.WriteLine("IvyBinding '" + attr.GetFormattedExpression(null) + "' to Method " + m.Name); EventHandler handler; #if (PocketPC) //Createdelegate mydlg = new Createdelegate(m, null, EventArgs.Empty); @@ -288,41 +370,43 @@ namespace IvyBus #else handler = (EventHandler)Delegate.CreateDelegate(typeof(EventHandler), m); #endif - BindMsg(attr.GetExpression(null), handler); + BindMsg(attr.GetFormattedExpression(null), handler); } } } // Autobinding on instance method - public void BindAttibute(object obj) + public void BindAttribute(object target) { - if (obj == null) return; - Type type = obj.GetType(); + if (target == null) return; + Type type = target.GetType(); //Get instance of the IvyBindingAttribute. foreach (MethodInfo m in type.GetMethods(BindingFlags.Instance | BindingFlags.NonPublic)) { foreach (IvyBindingAttribute attr in Attribute.GetCustomAttributes(m, typeof(IvyBindingAttribute))) { //TODO check paramater type MessageHandler - Ivy.traceProtocol("Ivy", "BindAttibute " + attr.GetExpression(obj) + "' to Method " + m.Name); + Ivy.traceProtocol(Resources.Ivy, "BindAttibute " + attr.GetFormattedExpression(target) + "' to Method " + m.Name); EventHandler handler; #if (PocketPC) handler = null; // TODO #else - handler = (EventHandler)Delegate.CreateDelegate(typeof(EventHandler), obj, m); + handler = (EventHandler)Delegate.CreateDelegate(typeof(EventHandler), target, m); #endif - BindMsg(attr.GetExpression(obj), handler); + BindMsg(attr.GetFormattedExpression(target), handler); } } } // Autobinding on IvyBindingAttribute method - public void BindAttibute(Assembly assy) + public void BindAttribute(Assembly target) { - foreach (Type typ in assy.GetTypes()) + if (target != null) { - BindAttibute(typ); + foreach (Type typ in target.GetTypes()) + { + BindAttribute(typ); + } } - } /// /// connects the Ivy bus to a domain or list of domains. @@ -337,9 +421,9 @@ namespace IvyBus /// One thread (serverThread/Ivy) to accept incoming connexions on server socket. /// a thread for each IvyClient when the connexion has been done. /// - public void Start(string domainbus) + public void Start(string domainBus) { - domainbus = GetDomain(domainbus); + domainBus = GetDomain(domainBus); try { long seed = DateTime.Now.Ticks / TimeSpan.TicksPerMillisecond; @@ -347,8 +431,8 @@ namespace IvyBus app = new MyTcpListener(IPAddress.Any, 0); app.Start(); // should be started before getting port - applicationHost = GetLocalIP(); - applicationPort = (ushort)((IPEndPoint)app.LocalEndpoint).Port; + applicationHost = LocalIP; + applicationPort = ((IPEndPoint)app.LocalEndpoint).Port; applicationUniqueId = string.Format(culture,"{0}:{1}:{2}", rand.Next(), seed, @@ -363,29 +447,22 @@ namespace IvyBus Ivy.traceProtocol("BindAttibute", "Ivy protocol: " + ProtocolVersion + " TCP service open on port " + applicationPort); watchers = new List(); - Domain[] d = parseDomains(domainbus); + 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 = new Thread(new ThreadStart(this.TcpListener)); serverThread.Name = "Ivy Tcp Server Thread"; stopped = false; + tcplistener_running = new AutoResetEvent(false); serverThread.Start(); -#if (PocketPC ) - Ivy.traceProtocol("Ivy", "Threading start in progress..."); - Thread.Sleep(100); -#else // Wait for readyness - while ( serverThread.ThreadState != System.Threading.ThreadState.Running || !app.IsActive()) - { - Ivy.traceError("BindAttibute", " Ivy Threading start in progress..." ); - Thread.Sleep( 100 ); - } -#endif + tcplistener_running.WaitOne(); + // sends the broadcasts and listen to incoming connexions for (int i = 0; i < watchers.Count; i++) { @@ -402,9 +479,9 @@ namespace IvyBus } /* a small private method for debbugging purposes */ - public static string Domains(string toparse) + public static string Domains(string toParse) { - string domainbus = GetDomain(toparse); + string domainbus = GetDomain(toParse); StringBuilder s = new StringBuilder("broadcasting on "); Ivy.Domain[] d = parseDomains(domainbus); for (int index = 0; index < d.Length; index++) @@ -438,7 +515,7 @@ namespace IvyBus lock (app) { stopped = true; - Ivy.traceProtocol("Ivy", "beginning stopping the bus"); + Ivy.traceProtocol(Resources.Ivy, "beginning stopping the bus"); try { // stopping the serverThread @@ -464,10 +541,10 @@ namespace IvyBus if (clients.Count != 0) { IvyClient[] copyClient; - copyClient = new IvyClient[clients.Count]; lock (clients) { - clients.CopyTo(copyClient, 0); + copyClient = new IvyClient[clients.Count]; + clients.CopyTo(copyClient); } foreach (IvyClient client in copyClient) { @@ -478,13 +555,35 @@ namespace IvyBus } catch (IOException e) { - Ivy.traceError("Ivy", "IOexception Stop " + e.Message); + Ivy.traceError(Resources.Ivy, "IOexception Stop " + e.Message); } - Ivy.traceProtocol("Ivy", "the bus should have stopped so far"); + Ivy.traceProtocol(Resources.Ivy, "the bus should have stopped so far"); } } - - + /// + /// join the main thread of Ivy ( ie wait until stopped ) + /// + /// + /// Performs a join on the Principal Thread. + /// + /// Number of millisecondes to wait before the Thread Stop. + /// + /// true if the thread stopped; false if it did not stop after the expiry of the period specified by the parameter millisecondsTimeout + /// + public bool Join(int millisecondsTimeout) + { + return serverThread.Join(millisecondsTimeout); + } + /// + /// Block the calling Thread until Ivy Stop + /// + /// + /// Performs a join on the Principal Thread. + /// + public void MainLoop() + { + this.Join(Timeout.Infinite); + } /// /// Send a formated message to someone on the bus /// @@ -501,60 +600,116 @@ namespace IvyBus /// public int SendMsg(string format, params object[] args) { + // send to everybody string msg = string.Format(culture, format, args); int count = 0; + // hash message in V4 protocol only + if (ProtocolVersion == 4) + IvyBindingSimple.Prepare(msg); // an alternate implementation would one sender thread per client // instead of one for all the clients. It might be a performance issue - lock (clients) + // Tentative of using BeginInvoke EndInvoke is slower + lock (client_bindings) { - // hash message in V4 protocol only - if (ProtocolVersion == 4) - IvyBindingSimple.Prepare(msg); - foreach (IvyClient client in clients) + foreach (IvyClientBinding clbind in client_bindings.Values) { - count += client.sendMsg(msg); + string[] matches = clbind.binding.Match(msg); + if (matches != null) + { + lock (clbind.client_bindind_ids) + { + + foreach (KeyValuePair> assoc in clbind.client_bindind_ids) + { + foreach (ushort id in assoc.Value) + { + count += assoc.Key.sendMsg(id, matches); + } + + } + + } + } + } + } + + return count; + } + + internal int SendMsgToClient(IvyClient clnt, string format, params object[] args) + { + string msg = string.Format(culture, format, args); + int count = 0; + // hash message in V4 protocol only + if (ProtocolVersion == 4) + IvyBindingSimple.Prepare(msg); + // an alternate implementation would one sender thread per client + // instead of one for all the clients. It might be a performance issue + lock (client_bindings) + { + + foreach (IvyClientBinding clbind in client_bindings.Values) + { + string[] matches = clbind.binding.Match(msg); + if (matches != null) + { + lock (clbind.client_bindind_ids) + { + if (clbind.client_bindind_ids.ContainsKey(clnt)) + { + List ids = clbind.client_bindind_ids[clnt]; + foreach (ushort id in ids) + { + count += clnt.sendMsg(id, matches); + } + } + } + } + } + } + + return count; } // - public ushort BindMsg(IvyApplicationBinding newbind) + public int BindMsg(IvyApplicationBinding newBinding) { - newbind.Key = serial++; + newBinding.Key = Interlocked.Increment(ref serial); - lock (bindings) bindings.Add(newbind.Key, newbind); + lock (bindings) bindings.Add(newBinding.Key, newBinding); // notifies the other clients this new regexp lock (clients) { foreach (IvyClient c in clients) { - c.stream.TokenAddBinding(newbind.Binding, newbind.Key, newbind.FormatedExpression); + c.stream.TokenAddBinding(newBinding.Binding, newBinding.Key, newBinding.FormattedExpression); } } - return newbind.Key; + return newBinding.Key; } /// /// Subscribes to a regular expression. /// /// a regular expression, groups are done with parenthesis - /// any objects implementing the Ivy.MessageListener + /// any objects implementing the EventHandler /// The args. /// the id of the 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. + /// the expression cant containt some dynamics argument replacement of the form %number[:objectFormat]% + /// the string will be replaced by arg[number].ToString(objectFormat) /// // - public ushort BindMsg(string regexp, EventHandler callback, params object[] args) + public int BindMsg(string expression, EventHandler callback, params object[] args) { // creates a new binding (regexp,callback) IvyApplicationBinding newbind; - newbind = new IvyApplicationBinding(); - newbind.Binding = BindingType.Regexp; - newbind.Expression = regexp; + newbind = new IvyApplicationBinding(BindingType.RegularExpression, expression, args); newbind.Callback += callback; - newbind.Args = args; return BindMsg(newbind); } @@ -562,7 +717,7 @@ namespace IvyBus /// unsubscribes a regular expression /// /// the id of the regular expression, returned when it was bound - public void UnbindMsg(ushort id) + public void UnbindMsg(int id) { if (!bindings.ContainsKey(id)) { @@ -572,11 +727,43 @@ namespace IvyBus { foreach (IvyClient c in clients) { - c.stream.TokenDelBinding(id); + try + { + c.stream.TokenDelBinding(id); + } + catch (IOException) + { + // client closed ignore it + } } } lock (bindings) bindings.Remove(id); } + public int ChangeMsg(int id, string expression) + { + IvyApplicationBinding newbind; + if (!bindings.ContainsKey(id)) + { + throw new IvyException("client wants to change an unexistant regexp " + id); + } + + // change binding (regexp,callback) + lock (bindings) + { + newbind = bindings[id]; + newbind.Expression = expression; + } + // notifies the other clients this new regexp + lock (clients) + { + foreach (IvyClient c in clients) + { + c.stream.TokenAddBinding(newbind.Binding, newbind.Key, newbind.FormattedExpression); + } + } + return id; + } + /// /// unsubscribes a regular expression @@ -625,11 +812,8 @@ namespace IvyBus { // creates a new binding (regexp,callback) IvyApplicationBinding newbind; - newbind = new IvyApplicationBinding(); - newbind.Binding = BindingType.Simple; - newbind.Expression = expression; + newbind = new IvyApplicationBinding(BindingType.Simple, expression, args); newbind.Callback += callback; - newbind.Args = args; return BindMsg(newbind); } /// @@ -640,9 +824,9 @@ namespace IvyBus /// public int Die(string target, string message) { - List v = GetClientsByName(target); - for (int i = 0; i < v.Count; i++) - v[i].stream.TokenDie(0, message); + ReadOnlyCollection v = GetClientsByName(target); + foreach (IvyClient clnt in v) + clnt.stream.TokenDie(0, message); return v.Count; } /// @@ -653,29 +837,23 @@ namespace IvyBus /// public int Ping(string target, string message) { - List v = GetClientsByName(target); - for (int i = 0; i < v.Count; i++) - v[i].stream.TokenPing(message); + ReadOnlyCollection v = GetClientsByName(target); + foreach (IvyClient clnt in v) + clnt.stream.TokenPing(message); return v.Count; } -#if (PocketPC) + + internal virtual void FireEvent(EventHandler ev, IvyEventArgs e) { if (ev != null) { +#if (PocketPC) if (parentControl != null) { parentControl.Invoke(ev, this, e); } - else - ev(this, e); - } - } #else - internal virtual void FireEvent(EventHandler ev, IvyEventArgs e) - { - if (ev != null) - { if (syncContext != null) { SendOrPostCallback update = delegate(object state) @@ -685,12 +863,13 @@ namespace IvyBus }; syncContext.Post(update, e); } +#endif else ev(this, e); } } -#endif + internal virtual void OnDirectMessage(IvyEventArgs e) { // Copy to a temporary variable to be thread-safe. @@ -712,7 +891,7 @@ namespace IvyBus FireEvent(temp,e); } #if (!PocketPC) - catch (SynchronizationLockException ex) + catch (SynchronizationLockException) { // protect terminaison } @@ -735,6 +914,12 @@ namespace IvyBus EventHandler temp = BindingRemove; FireEvent(temp,e); } + internal virtual void OnClientChangeBinding(IvyEventArgs e) + { + // Copy to a temporary variable to be thread-safe. + EventHandler temp = BindingChange; + FireEvent(temp, e); + } internal virtual void OnClientFilterBinding(IvyEventArgs e) { // Copy to a temporary variable to be thread-safe. @@ -786,12 +971,12 @@ namespace IvyBus #endif internal void OnMessage(IvyMessageEventArgs e) { - IvyApplicationBinding bind = bindings[e.Id]; - - if (bind == null) + if (!bindings.ContainsKey( e.Id)) { throw new IvyException("(callCallback) Not regexp matching id " + e.Id); } + IvyApplicationBinding bind = bindings[e.Id]; + #if(PocketPC) bind.Firevent(parentControl, e); #else @@ -808,6 +993,24 @@ namespace IvyBus { clients.Remove(c); } + List purge_bind = new List(); + lock (client_bindings) + { + foreach (IvyClientBinding clbind in client_bindings.Values) + { + lock (clbind.client_bindind_ids) + { + clbind.client_bindind_ids.Remove(c); + if ( clbind.client_bindind_ids.Count == 0 ) + purge_bind.Add( clbind.binding.Expression); + } + } + // remove Binding if no client + foreach ( string expr in purge_bind ) + { + client_bindings.Remove(expr); + } + } } @@ -816,7 +1019,7 @@ namespace IvyBus /// /// The name of the Ivy agent you're looking for /// - public List GetClientsByName(string name) + public ReadOnlyCollection GetClientsByName(string name) { List v = new List(); foreach (IvyClient ic in clients) @@ -824,7 +1027,7 @@ namespace IvyBus if (ic.ApplicationName.CompareTo(name) == 0) v.Add(ic); } - return v; + return new ReadOnlyCollection(v); } /////////////////////////////////////////////////////////////////: @@ -833,34 +1036,37 @@ namespace IvyBus // /////////////////////////////////////////////////////////////////: - internal void addClient(Socket socket, string appname) + internal void addClient(IvyClient client) { if (stopped) return; - IvyClient client = new IvyClient(this, socket, appname); + lock (clients) { clients.Add(client); } - client.SendBindings(); + } - public static IPAddress GetLocalIP() + public static IPAddress LocalIP { - IPAddress returnaddr = null; - //TODO remove ALL reverse DNS search !!!! - IPHostEntry ip = Dns.GetHostEntry(Dns.GetHostName()); - foreach (IPAddress addr in ip.AddressList) + get { - returnaddr = addr; - if (IPAddress.IsLoopback(addr)) continue; - break; + IPAddress returnaddr = null; + //TODO remove ALL reverse DNS search !!!! + IPHostEntry ip = Dns.GetHostEntry(Dns.GetHostName()); + foreach (IPAddress addr in ip.AddressList) + { + returnaddr = addr; + if (IPAddress.IsLoopback(addr)) continue; + break; + } + return returnaddr; } - return returnaddr; } - public static string GetDomain(string domainbus) + public static string GetDomain(string domainBus) { #if (PocketPC) // TODO integrate in normal version if (domainbus == null || domainbus.Length == 0) @@ -885,19 +1091,19 @@ namespace IvyBus domainbus = bcast + ":" + Domain.getPort(domainbus); } #else - if (domainbus == null || domainbus.Length == 0 ) + if (domainBus == null || domainBus.Length == 0 ) { - domainbus = Environment.GetEnvironmentVariable("IVYBUS"); + domainBus = Environment.GetEnvironmentVariable("IVYBUS"); } - if (domainbus == null || domainbus.Length == 0) + if (domainBus == null || domainBus.Length == 0) { - domainbus = Properties.Settings.Default.IvyBus; + domainBus = Properties.Settings.Default.IvyBus; } #endif - if (domainbus == null || domainbus.Length == 0) - domainbus = DEFAULT_DOMAIN; - return domainbus; + if (domainBus == null || domainBus.Length == 0) + domainBus = DefaultDomain; + return domainBus; } @@ -928,50 +1134,61 @@ namespace IvyBus * 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) + internal IvyClient checkConnected(IvyClient clnt) { + IvyClient sameClnt = null; if (clnt.AppPort == 0) - return false; + { + Console.WriteLine(" client {0} port == 0 ", clnt.appName); + return sameClnt; + } lock (clients) { foreach (IvyClient client in clients) { - if (clnt != client && client.sameClient(clnt)) - return true; + if (clnt == client) continue; // SKIP himself + if (client.sameIvyClient(clnt)) + { + sameClnt = client; + break; + } } } - return false; + return sameClnt; } /* * the service socket thread reader main loop */ - private void Run() + private void TcpListener() { - Ivy.traceProtocol("Ivy", "Ivy service Thread started"); + Ivy.traceProtocol(Resources.Ivy, "Ivy service Thread started"); bool running = true; + tcplistener_running.Set(); while (running) { try { Socket socket = app.AcceptSocket(); + // early disconnexion if (stopped) break; - // early disconnexion - addClient(socket, "Unkown(waiting for name reception)"); // the peer called me + // the peer called me + IvyClient client = new IvyClient(this, socket, "Unkown(waiting for name reception)",0); + client.SendBindings(); //TODO in a Thread or wait for the peer to sent his before sending mine + } catch (IOException e) { - Ivy.traceError("Ivy","Ivy server socket reader caught an exception: " + e.Message); + Ivy.traceError(Resources.Ivy,Resources.IvyIOException + e.Message); } catch (SocketException e) { - Ivy.traceError("Ivy","my server socket has been closed " + e.Message); + Ivy.traceError(Resources.Ivy,Resources.IvySocketException + e.Message); running = false; } } - Ivy.traceProtocol("Ivy", "Ivy service Thread stopped"); + Ivy.traceProtocol(Resources.Ivy, "Ivy service Thread stopped"); } [Conditional("DEBUG")] @@ -1005,14 +1222,13 @@ namespace IvyBus } private string domainaddr; private int port; - public Domain(string net) + public Domain(string net):this( getDomain(net),getPort(net)) { - this.domainaddr = getDomain(net); - this.port = getPort(net); } public Domain(string domainaddr, int port) { - this.domainaddr = domainaddr; this.port = port; + this.domainaddr = domainaddr; + this.port = port; } public override string ToString() { @@ -1033,7 +1249,7 @@ namespace IvyBus } catch (ArgumentException e) { - Ivy.traceError("Ivy","Bad broascat addr " + net + "error " + e.Message); + Ivy.traceError(Resources.Ivy,Resources.BadBroadcast + net + "error " + e.Message); return null; } return net; @@ -1041,18 +1257,18 @@ namespace IvyBus public static int getPort(string net) { - if (net == null) return Ivy.DEFAULT_PORT; + if (net == null) { return Ivy.DefaultPort; } int sep_index = net.LastIndexOf(":"); - int port = (sep_index == -1) ? Ivy.DEFAULT_PORT : Int32.Parse(net.Substring(sep_index + 1)); + int port = (sep_index == -1) ? Ivy.DefaultPort : Int32.Parse(net.Substring(sep_index + 1)); return port; } } - public static bool ValidatingDomain(string p) + public static bool ValidatingDomain(string domain) { // domain if of the form ip1[:port][,ip2[:port]] with ip of the form n1.n2.n3.n4 - return Regex.IsMatch(p, @"\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}:\d+"); + return Regex.IsMatch(domain, @"\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}:\d+"); } } -- cgit v1.1