summaryrefslogtreecommitdiff
path: root/IvyProbeConsole/IvyProbeConsole.cs
diff options
context:
space:
mode:
Diffstat (limited to 'IvyProbeConsole/IvyProbeConsole.cs')
-rw-r--r--IvyProbeConsole/IvyProbeConsole.cs373
1 files changed, 373 insertions, 0 deletions
diff --git a/IvyProbeConsole/IvyProbeConsole.cs b/IvyProbeConsole/IvyProbeConsole.cs
new file mode 100644
index 0000000..516d702
--- /dev/null
+++ b/IvyProbeConsole/IvyProbeConsole.cs
@@ -0,0 +1,373 @@
+/// François-Régis Colin
+/// http://www.tls.cena.fr/products/ivy/
+/// *
+/// (C) CENA
+/// *
+namespace IvyProbeConsole
+{
+ using System;
+ using System.Collections;
+ using System.Collections.Generic;
+ using System.Threading;
+ using System.Text.RegularExpressions;
+ using System.IO;
+ using System.Configuration;
+ using System.Diagnostics;
+ using IvyBus;
+ using Gnu;
+
+ /// <summary> Console implementation of the ivyprobe test program.
+ /// </summary>
+ /// <remarks>Mainly used for testing and debugging purpose</remarks>
+ public class IvyProbeConsole
+ {
+ public virtual bool ExitOnDie
+ {
+ set
+ {
+ exitOnDie = value;
+ }
+
+ }
+ public void BindFromFile(string name)
+ {
+ string line;
+ try
+ {
+ FileStream file = new FileStream(name, FileMode.Open, FileAccess.Read);
+ TextReader reader = new StreamReader(file);
+ while ((line = reader.ReadLine()) != null)
+ {
+ bus.BindMsg(line, receive);
+ }
+ }
+ catch (FileNotFoundException e)
+ {
+ Console.WriteLine(e.Message);
+ }
+ }
+ public const string helpCommands =
+ "Available commands:\n"+
+ ".die CLIENTNAME sends a die message\n" +
+ ".direct CLIENTNAME ID MESSAGE sends the direct message to the client, with a message id set to the numerical ID\n" +
+ ".bye quits the application\n" +
+ ".quit idem\n" +
+ ".list lists the available clients\n" +
+ ".ping sends a ping request if IVY_PING is enabled\n" +
+ ".bind REGEXP binds to a regexp at runtime\n" +
+ ".unbind REGEXP unbinds to a regexp at runtime";
+
+ public const String helpmsg =
+ "usage: IvyProbe [options] [regexp]\n" +
+ "\t-b BUS\tspecifies the Ivy bus domain\n" +
+ "\t-n ivyname (default JPROBE)\n" +
+ "\t-q\tquiet, no tty output\n" +
+ "\t-d\tdebug\n" +
+ "\t-t\ttime stamp each message\n" +
+ "\t-h\thelp\n\n" +
+ "\t regexp is a Perl5 compatible regular expression";
+
+ private TextReader in_Renamed;
+ private volatile Thread looperThread;
+ private Ivy bus;
+ private bool timestamp, quiet, debug, exitOnDie = false;
+ enum Command {
+ direct,
+ die,
+ unbind,
+ bind,
+ ping,
+ quit,
+ bye,
+ list,
+ help};
+ const string reg_parse =
+ @"^\.(?<cmd>direct) (?<target>[^ ]*) (?<id>[0-9]+) (?<message>.*)$|" +
+ @"^\.(?<cmd>die) (?<target>.*)$|" +
+ @"^\.(?<cmd>unbind) (?<target>.*)$|" +
+ @"^\.(?<cmd>bind) (?<target>.*)$|" +
+ @"^\.(?<cmd>ping) (?<target>.*)$|" +
+ @"^\.(?<cmd>quit)$|" +
+ @"^\.(?<cmd>bye)$|" +
+ @"^\.(?<cmd>list)$|" +
+ @"^\.(?<cmd>help)$|";
+ private Regex cmd_regexp;
+
+ [STAThread]
+ public static void Main(String[] args)
+ {
+ string name = "C#PROBE";
+ string fname = null;
+ bool quiet = false;
+ bool timestamp = false;
+ string domain = Ivy.GetDomain(null);
+ bool debug = false;
+
+ domain = Properties.Settings.Default.domain;
+ name = Properties.Settings.Default.name;
+ quiet = Properties.Settings.Default.quiet;
+ timestamp = Properties.Settings.Default.timestamp;
+ debug = Properties.Settings.Default.IvyDebug;
+
+
+ GetOpt opt = new GetOpt(args, "f:n:b:dqht");
+ Arg a;
+ while ((a = opt.NextArg()) != null)
+ {
+ switch (a.Flag)
+ {
+ case 'd':
+ debug = true;
+ break;
+
+ case 'b':
+ domain = a.Parameter;
+ break;
+
+ case 'n':
+ name = a.Parameter;
+ break;
+ case 'f':
+ fname = a.Parameter;
+ break;
+
+ case 'q':
+ quiet = true;
+ break;
+
+ case 't':
+ timestamp = true;
+ break;
+
+ case 'h': default:
+ System.Console.Out.WriteLine(helpmsg);
+ System.Environment.Exit(0);
+ break;
+
+ }
+ }
+
+
+ IvyProbeConsole p = new IvyProbeConsole(System.Console.In, timestamp, quiet, debug );
+ p.ExitOnDie = true;
+ Ivy bus = new Ivy(name, name + " ready");
+ p.start(bus);
+
+ if (fname != null)
+ p.BindFromFile(fname);
+
+ foreach(string ex in opt.Extras)
+ {
+ if (!quiet)
+ System.Console.Out.WriteLine("you want to subscribe to " + ex);
+ bus.BindMsg(ex, p.receive);
+ }
+
+ if (!quiet)
+ System.Console.Out.WriteLine(Ivy.Domains(domain));
+
+ bus.Start(domain);
+
+ }
+
+
+
+
+ public IvyProbeConsole(TextReader in_Renamed, bool timestamp, bool quiet, bool debug)
+ {
+ this.in_Renamed = in_Renamed;
+ this.timestamp = timestamp;
+ this.quiet = quiet;
+ this.debug = debug;
+ try
+ {
+ cmd_regexp = new Regex(reg_parse, RegexOptions.IgnoreCase);
+ }
+ catch (ArgumentException ree)
+ {
+ System.Console.Error.WriteLine("Regexp fatal error in the Probe program.");
+ System.Console.Error.WriteLine(ree.StackTrace);
+ System.Environment.Exit(0);
+ }
+ }
+
+ public virtual void start(Ivy bus)
+ {
+ if (looperThread != null)
+ throw new IvyException("Probe already started");
+ this.bus = bus;
+
+ bus.ClientConnected += connect;
+ bus.ClientDisconnected += disconnect;
+ bus.DieReceived += die ;
+ bus.DirectMessageReceived += directMessage;
+ bus.BindingAdd += new EventHandler<IvyEventArgs>(bus_BindingAdd);
+ bus.BindingRemove += new EventHandler<IvyEventArgs>(bus_BindingRemove);
+ bus.BindingFilter += new EventHandler<IvyEventArgs>(bus_BindingFilter);
+
+ looperThread = new Thread(new ThreadStart(Run));
+ looperThread.Name = "Keyboard Input Thread";
+ looperThread.Start();
+ }
+
+ void bus_BindingFilter(object sender, IvyEventArgs e)
+ {
+ println("filtred regexp {0} from {1}", e.Argument, e.Client.ApplicationName);
+ }
+
+ void bus_BindingRemove(object sender, IvyEventArgs e)
+ {
+ println("Removed regexp {0} from {1}", e.Argument, e.Client.ApplicationName);
+ }
+
+ void bus_BindingAdd(object sender, IvyEventArgs e)
+ {
+ println("Added regexp {0} from {1}", e.Argument, e.Client.ApplicationName);
+ }
+
+
+ public void Run()
+ {
+ traceDebug("Thread started");
+ Thread thisThread = Thread.CurrentThread;
+ String s;
+ // "infinite" loop on keyboard input
+ while (looperThread == thisThread)
+ {
+ s = in_Renamed.ReadLine();
+ if (s == null)
+ break;
+ if (s.Length == 0) continue;
+ if ( s.StartsWith( ".") )
+ parseCommand(s);
+ else
+ {
+ println("-> Sent to " + bus.SendMsg(s) + " peers");
+ }
+ }
+ println("End of input. Good bye !");
+ bus.Stop();
+ traceDebug("Probe Thread stopped");
+ }
+
+ internal void parseCommand(string s)
+ {
+ Match result;
+ traceDebug("parsing the [" + s + "] (length " + s.Length + ") string");
+
+ result = cmd_regexp.Match(s);
+
+
+ if (result.Success)
+ {
+ string cmd = result.Groups["cmd"].Value;
+ string target;
+ try
+ {
+ Command TheCommand = (Command)Enum.Parse(typeof(Command), cmd);
+
+ switch ( TheCommand )
+ {
+ case Command.direct:
+ {
+ target = result.Groups["target"].Value;
+ ushort id = ushort.Parse(result.Groups["id"].Value);
+ string message = result.Groups["message"].Value;
+ List<IvyClient> v = bus.GetClientsByName(target);
+ if (v.Count == 0)
+ println("no Ivy client with the name \"" + target + "\"");
+ for (int i = 0; i < v.Count; i++)
+ v[i].SendDirectMsg(id, message);
+ }
+ break;
+ case Command.die:
+ target = result.Groups["target"].Value;
+ if (bus.Die(target, ".die command") == 0)
+ println("no Ivy client with the name \"" + target + "\"");
+ break;
+ case Command.unbind:
+ target = result.Groups["target"].Value;
+ if (bus.UnbindMsg(target))
+ println("you want to unsubscribe to " + target);
+ else
+ println("you can't unsubscribe to " + target + ", your're not subscribed to it");
+ break;
+ case Command.bind:
+ target = result.Groups["target"].Value;
+ println("you want to subscribe to " + target);
+ bus.BindMsg(target, receive);
+ break;
+ case Command.ping:
+ target = result.Groups["target"].Value;
+ if (bus.Ping(target, "test") == 0)
+ println("no Ivy client with the name \"" + target + "\"");
+ break;
+ case Command.quit:
+ case Command.bye:
+ bus.Stop();
+ System.Environment.Exit(0);
+ break;
+ case Command.list:
+ println(bus.IvyClients.Count + " clients on the bus");
+ foreach (IvyClient client in bus.IvyClients )
+ println("-> " + client.ApplicationName);
+ break;
+ case Command.help:
+ println(helpCommands);
+ break;
+ }
+ }
+ catch (ArgumentException)
+ {
+ Console.WriteLine("manque de la commande dans l'enum");
+ }
+ }
+
+ }
+ // parseCommand
+
+ private void connect(object sender, IvyEventArgs e)
+ {
+ println(e.Client.ApplicationName + " connected from "+e.Client.RemoteAddress+":"+e.Client.RemotePort);
+ }
+
+ private void disconnect(object sender, IvyEventArgs e)
+ {
+ println(e.Client.ApplicationName + " disconnected ");
+ }
+
+ private void die(object sender, IvyDieEventArgs e)
+ {
+ println("received die msg from " + e.Client.ApplicationName + " good bye cause: "+e.Argument);
+ /* I cannot stop the readLine(), because it is native code */
+ if (exitOnDie)
+ System.Environment.Exit(0);
+ }
+
+ private void directMessage(object sender, IvyEventArgs e)
+ {
+ println(e.Client.ApplicationName + " direct Message " + e.Id + e.Argument);
+ }
+
+ private void receive(object sender, IvyMessageEventArgs e)
+ {
+ String s = e.Client.ApplicationName + " sent ";
+ s += string.Join(",", e.Arguments);
+ println(s);
+ }
+ [Conditional("DEBUG")]
+ private void traceDebug(String s)
+ {
+ Trace.WriteLineIf(debug, "-->Probe<-- " + s);
+ }
+ private void println(string format, params object[] args)
+ {
+ if (!quiet)
+ {
+ if (timestamp) System.Console.Out.Write(string.Format("[ {0|HH:mm:ss.fff} ]",System.DateTime.Now ));
+ System.Console.Out.WriteLine(string.Format(format,args));
+ }
+ }
+
+ }
+} \ No newline at end of file