summaryrefslogtreecommitdiff
path: root/Ivy/IvyPPC/IvyClient.cs
diff options
context:
space:
mode:
Diffstat (limited to 'Ivy/IvyPPC/IvyClient.cs')
-rw-r--r--Ivy/IvyPPC/IvyClient.cs592
1 files changed, 0 insertions, 592 deletions
diff --git a/Ivy/IvyPPC/IvyClient.cs b/Ivy/IvyPPC/IvyClient.cs
deleted file mode 100644
index 3db9f0f..0000000
--- a/Ivy/IvyPPC/IvyClient.cs
+++ /dev/null
@@ -1,592 +0,0 @@
-/// François-Régis Colin
-/// http://www.tls.cena.fr/products/ivy/
-/// *
-/// (C) CENA
-/// *
-namespace IvyBus
-{
- using System;
- using System.Collections;
- using System.Collections.Specialized;
- using System.Collections.Generic;
- using System.Threading;
- using System.Text;
- using System.IO;
- using System.Net;
- using System.Net.Sockets;
- using System.Configuration;
- using System.Diagnostics;
-
- /// <summary> A Class for the the peers on the bus.
- /// </summary>
- /// <remarks>
- /// each time a connexion is made with a remote peer, the regexp are exchanged
- /// once ready, a ready message is sent, and then we can send messages,
- /// die messages, direct messages, add or remove regexps, or quit. A thread is
- /// created for each remote client.
- /// </remarks>
- public class IvyClient : IvyProtocol, IComparable<IvyClient>, IDisposable
- {
- public int CompareTo(IvyClient other)
- {
- return (other.clientPriority - clientPriority);
- }
-
- public String ApplicationName
- {
- get
- {
- return appName;
- }
-
- }
-
- public List<string> Regexps
- {
- get
- {
- List<string> tab = new List<string>();
- lock (bindings)
- {
- foreach (IvyBindingBase bind in bindings.Values)
- tab.Add(bind.Expression);
- }
- return tab;
- }
-
- }
- internal int AppPort
- {
- get
- {
- return appPort;
- }
-
- }
- public IPAddress RemoteAddress
- {
- get
- {
- return remoteHost;
- }
-
- }
- public int RemotePort
- {
- get
- {
- return remotePort;
- }
-
- }
-
- private Ivy bus;
- private Dictionary<ushort,IvyBindingBase> bindings;
- private int appPort;
- private string clientId; /* an unique ID for each IvyClient */
- private int clientPriority; /* client priority */
-
- private volatile Thread clientThread; // volatile to ensure the quick communication
- private bool doping; // false by runtime default
- private const int PINGTIMEOUT = 5000;
- private volatile Thread pingerThread;
-
- private int remotePort;
- private IPAddress remoteHost;
-
- // protected variables
- internal String appName;
- internal IvyProtocol stream;
-
- internal IvyClient(Ivy bus, Socket socket, string appname)
- {
- bindings = new Dictionary<ushort,IvyBindingBase>();
- appName = appname;
- this.bus = bus;
-
- IPEndPoint endpoint = (IPEndPoint)socket.RemoteEndPoint;
-
- remoteHost = endpoint.Address;
- remotePort = endpoint.Port;
-
-#if (!PocketPC )
- socket.SetSocketOption( SocketOptionLevel.Tcp, SocketOptionName.KeepAlive, 1 );
-#endif
-
- if ( bus.ProtocolVersion == 4 )
- stream = new IvyTCPStreamV4( socket, this );
- else
- stream = new IvyTCPStreamV3(socket, this);
-
- clientPriority = Ivy.DEFAULT_PRIORITY;
- // spawns a thread to manage the incoming traffic on this
- // socket. We should be ready to receive messages now.
- clientThread = new Thread(new ThreadStart(this.Run));
- clientThread.Name = "Ivy Tcp Client Reader Thread ("+appname+")";
- clientThread.Start();
-
- }
-
- internal void SendBindings()
- {
- try
- {
- stream.TokenApplicationId(bus.applicationPriority, bus.AppId);
-
- // sends our ID, whether we initiated the connexion or not
- // the ID is the couple "host name,application Port", the host name
- // information is in the socket itself, the port is not known if we
- // initiate the connexion
- stream.TokenStartRegexp(bus.applicationPort, bus.appName);
- // sends our regexps to the peer
- lock (bus.bindings)
- {
- foreach (IvyApplicationBinding bind in bus.bindings.Values)
- {
- stream.TokenAddBinding(bind.Binding, bind.Key, bind.FormatedExpression);
- }
- }
- stream.TokenEndRegexp();
-
-#if (!PocketPC)
- doping = Properties.Settings.Default.IvyPing;
-#endif
- if (doping)
- {
- pingerThread = new Thread(new ThreadStart(PingerRun));
- pingerThread.Name = "Ivy Pinger Thread";
- pingerThread.Start();
- }
-
-
- }
- catch (IOException ex)
- { // the client nous a coupé l'herbe sous le pied
- Ivy.traceError("IvyClient","I can't send my message to this client. He probably left " + ex.Message);
- // invokes the Disconnected applicationListeners
- //bus.OnClientDisconnected(new IvyEventArgs(this,id, message ));
- // called by the receiver Thread
- close(false);
- }
- }
-
- /// <summary> returns the name of the remote agent.
- /// allow an Ivy package class to access the list of regexps at a
- /// given time.
- /// perhaps we should implement a new IvyApplicationListener method to
- /// allow the notification of regexp addition and deletion
- /// </summary>
-
- /// <summary> sends a direct message to the peer
- /// </summary>
- /// <param name='id'>the numeric value provided to the remote client
- /// </param>
- /// <param name='message'>the string that will be match-tested
- ///
- /// </param>
- public void SendDirectMsg(ushort id, string message)
- {
- try
- {
- stream.TokenDirectMsg( id, message);
- }
- catch (IOException ex)
- {
- Ivy.traceError("IvyClient","I can't send my message to this client. He probably left "+ex.Message);
- // first, I'm not a first class IvyClient any more
- bus.removeClient(this);
- // invokes the Disconnected applicationListeners
- //bus.OnClientDisconnected(new IvyEventArgs(this,id, message ));
- // should be called by receiver thread
- close(false);
- }
- }
-
- /// <summary> closes the connexion to the peer.
- /// </summary>
- /// <param name='notify'>should I send Bye message ?
- /// the thread managing the socket is stopped
- ///
- /// </param>
- internal void close(bool notify)
- {
- Ivy.traceProtocol("IvyClient","closing connexion to " + appName);
- if (doping )
- {
- StopPinging();
- }
- if (notify)
- try
- {
- stream.TokenBye(0, "hasta la vista");
- }
- catch (IOException ioe)
- {
- throw new IvyException(ioe.Message);
- }
- // stop the thread and close the stream
- if (clientThread == null)
- return;
- // Tell Thread to stop.
- if (stream != null)
- {
- try
- {
- stream.Close(); // should stop the Reading Client Thread
- }
- catch (IOException ioe)
- {
- throw new IvyException(ioe.Message);
- }
- //socket.Close(); // pris en charge par stream ( NetWorkStream )
- stream = null;
- }
- // Potential dead lok when thread issue ClientDisconnected event
- //if (Thread.CurrentThread != clientThread && (clientThread != null))
- //{
- // // Wait for Thread to end.
- // bool term = clientThread.Join(10000);
- // if (!term && (clientThread != null)) clientThread.Abort();
- //}
-
- clientThread = null;
-
-
- }
-
- /// <summary> sends the substrings of a message to the peer for each matching regexp.
- /// </summary>
- /// <param name='message'>the string that will be match-tested
- /// </param>
- /// <returns>the number of messages sent to the peer
- ///
- /// </returns>
- internal int sendMsg(String message)
- {
- int count = 0;
-
- lock( bindings )
- {
- try
- {
- foreach (IvyBindingBase bind in bindings.Values)
- {
- string[] args = bind.Match(message);
- if (stream != null && args != null)
- {
- stream.TokenMsg(bind.Key, args);
- count++;
- }
- }
- }
- catch (IOException ex)
- {
- Ivy.traceError("IvyClient","I can't send my message to this client. He probably left " + ex.Message);
- // first, I'm not a first class IvyClient any more
- bus.removeClient(this);
- // invokes the Disconnected applicationListeners
- // in the receiver thread
- close(false);
- }
-
-
- }
- return count;
- }
-
- /// <summary> compares two peers the id is the couple (host,service port).
- /// </summary>
- /// <param name='clnt'>the other peer
- /// </param>
- /// <returns>true if the peers are similir. This should not happen, it is bad
- /// © ® (tm)
- ///
- /// </returns>
- internal bool sameClient(IvyClient clnt)
- {
- return (appPort != 0 && appPort == clnt.appPort) && (RemoteAddress == clnt.RemoteAddress);
- }
-
- /// <summary> the code of the thread handling the incoming messages.
- /// </summary>
- private void Run()
- {
- Ivy.traceProtocol("IvyClient","Connected from " + RemoteAddress + ":" + RemotePort);
-
- Ivy.traceProtocol("IvyClient","Thread started");
-
- bool running = true;
- while ( running && (stream != null) )
- {
- try
- {
- if ( stream.receiveMsg() )
- {
- // early stop during readLine()
- if (doping && (pingerThread != null))
- pingerThread.Abort();
- }
- else
- {
- Ivy.traceProtocol("IvyClient","receiveMsg false ! leaving the thread");
- running = false;
- break;
- }
- }
- catch ( ObjectDisposedException ex )
- {
- Ivy.traceError("IvyClient", "socket closed "+ex.Message );
- running = false;
- break;
- }
- catch (IvyException ie)
- {
- Ivy.traceError("IvyClient","socket closed IvyException" + ie.Message);
- running = false;
- break;
- }
- catch (SocketException se)
- {
- Ivy.traceError("IvyClient", "socket closed "+se.Message );
- running = false;
- break;
- }
- catch (IOException ex)
- {
- if ( ex.InnerException is SocketException )
- {
- Ivy.traceProtocol("IvyClient", "socket closed" );
-
- }
- else
- {
- Ivy.traceError("IvyClient","abnormally Disconnected from " + RemoteAddress + ":" + RemotePort);
- }
- running = false;
- break;
- }
- }
- Ivy.traceProtocol("IvyClient","normally Disconnected from " + appName);
- Ivy.traceProtocol("IvyClient","Thread stopped");
- // invokes the Disconnected applicationListeners
- bus.OnClientDisconnected(new IvyEventArgs(this,0, "" ));
- // first, I'm not a first class IvyClient any more
- if (stream != null)
- {
- stream.Close();
- stream = null;
- }
- bus.removeClient(this);
-
- }
- void IvyProtocol.Close()
- {
- // never call in this side
- }
- bool IvyProtocol.receiveMsg()
- {
- // nerver call in this side
- return false;
- }
- void IvyProtocol.TokenDie(ushort id, string arg)
- {
- Ivy.traceProtocol("IvyClient","received die Message from " + appName + "Raison: "+ arg);
- // invokes the die applicationListeners
- IvyDieEventArgs ev = new IvyDieEventArgs(this, id, arg);
- bus.OnDie(ev);
- // first, I'm not a first class IvyClient any more
- bus.removeClient(this);
- // makes the bus die
- bus.Stop();
- close(false);
- if (ev.ForceExit)
-#if (PocketPC)
- System.Windows.Forms.Application.Exit();
-#else
- System.Environment.Exit(0);
-#endif
- }
- void IvyProtocol.TokenBye(ushort err, string arg)
- {
- // the peer quits
- Ivy.traceProtocol("IvyClient","received bye Message from " + appName + "Raison: "+ arg);
- // first, I'm not a first class IvyClient any more
- //bus.removeClient(this); // this is done in the receive thread terminaison!!
- // invokes the disconnect applicationListeners
- //bus.FireClientDisconnected(this); done in Running Thread
- close(false); // will fire disconnected
- }
-
- void IvyProtocol.TokenAddBinding(BindingType type, ushort id, string expression)
- {
-
- if (type == BindingType.Regexp && !bus.CheckRegexp(expression))
- {
- bus.OnClientFilterBinding(new IvyEventArgs(this, id, expression ));
- return;
- }
- IvyBindingBase bind = null;
- try
- {
- switch (type)
- {
- case BindingType.Regexp:
- bind = new IvyBindingRegexp(id, expression);
- break;
- case BindingType.Simple:
- bind = new IvyBindingSimple(id, expression);
- break;
- }
- lock (bindings)
- {
- bindings.Add(id, bind);
- }
-
- bus.OnClientAddBinding(new IvyEventArgs(this, id, expression));
-
- }
- catch (ArgumentException ex)
- {
- throw new IvyException("binding expression error " + ex.Message);
- }
-
- }
- void IvyProtocol.TokenDelBinding(ushort id)
- {
- lock( bindings )
- {
- try
- {
- IvyBindingBase bind = bindings[id];
- bus.OnClientRemoveBinding(new IvyEventArgs(this, bind.Key, bind.Expression));
- bindings.Remove(id);
- }
- catch (KeyNotFoundException ex)
- {
- Ivy.traceError("IvyClient","DelBinding " + ex.Message);
- }
- }
- }
- void IvyProtocol.TokenMsg(ushort id, string[] args)
- {
- bus.OnMessage(new IvyMessageEventArgs(this, id, args));
- }
- void IvyProtocol.TokenError(ushort id, string arg)
- {
- bus.OnError(new IvyEventArgs(this, id, arg));
- Ivy.traceError("IvyClient","Error msg " + id + " " + arg);
- }
- void IvyProtocol.TokenApplicationId(ushort id, string arg)
- {
- clientId = arg;
- if ( clientPriority != id )
- {
- clientPriority = id;
- bus.SortClients();
- }
- }
- void IvyProtocol.TokenEndRegexp()
- {
- /*
- * the peer is perhaps not ready to handle this message
- * an assymetric processing should be written
- */
- if (bus.ReadyMessage != null)
- sendMsg(bus.ReadyMessage);
- bus.OnClientConnected(new IvyEventArgs(this, 0, ""));
- }
- void IvyProtocol.TokenStartRegexp(ushort id, string arg)
- {
- appName = arg;
- appPort = id;
- if (bus.checkConnected(this))
- {
- close(false);
- throw new IvyException("Rare ! A concurrent connect occured");
- }
-
- }
- void IvyProtocol.TokenDirectMsg(ushort id, string arg)
- {
- bus.OnDirectMessage(new IvyEventArgs(this,id,arg));
- }
- void IvyProtocol.TokenPing(string arg)
- {
- // I receive a ping. I can answer a pong.
- Ivy.traceProtocol("IvyClient","Ping msg from " + appName + " : " + arg );
- stream.TokenPong(arg);
- }
- void IvyProtocol.TokenPong(string arg)
- {
- Ivy.traceProtocol("IvyClient","Ping msg from " + appName + " : " + arg);
- }
-
-
-
- public override String ToString()
- {
- return "IvyClient " + bus.appName + ":" + appName;
- }
-
- /* is the Pinging Thread Runninng */
- internal bool isPinging;
-
- private void PingerRun()
- {
- isPinging = true;
- Ivy.traceProtocol("IvyClient","Pinger Thread started");
- while (isPinging)
- {
- try
- {
- Thread.Sleep(PINGTIMEOUT);
- stream.TokenPing("are you here ?");
- }
- catch (ThreadAbortException ie)
- {
- Ivy.traceError("IvyClient","Pinger Thread killed "+ie.Message);
- }
- }
- Ivy.traceProtocol("IvyClient","Pinger Thread stopped");
- }
- public virtual void StopPinging()
- {
- isPinging = false;
- //pingerThread.Interrupt();
- pingerThread.Abort();
- }
-
- #region IDisposable Members
-
- //Implement IDisposable.
- public void Dispose()
- {
- Dispose(true);
- GC.SuppressFinalize(this);
- }
-
- protected virtual void Dispose(bool disposing)
- {
- if (disposing)
- {
- // Free other state (managed objects).
- }
- // Free your own state (unmanaged objects).
- // Set large fields to null.
- if (stream != null)
- {
- stream.Close();
- stream = null;
- }
- }
-
- // Use C# destructor syntax for finalization code.
- ~IvyClient()
- {
- // Simply call Dispose(false).
- Dispose(false);
- }
-
- #endregion
- }
-} \ No newline at end of file