/// 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; /// Console implementation of the ivyprobe test program. /// /// Mainly used for testing and debugging purpose public class IvyProbeConsole { public virtual bool ExitOnDie { set { exitOnDie = value; } } 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; private Regex directMsgRE; [STAThread] public static void Main(String[] args) { String name = "C#PROBE"; 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, "n:b:dqht"); Arg a; while ((a = opt.NextArg()) != null) { switch (a.Flag) { case 'd': //UPGRADE_ISSUE: Method 'java.lang.System.getProperties' was not converted. 'ms-help://MS.VSCC/commoner/redir/redirect.htm?keyword="jlca1000_javalangSystemgetProperties"' //System.Configuration.AppSettingsReader sysProp = System.getProperties(); //SupportClass.PutElement(sysProp, "IVY_DEBUG", "yes"); break; case 'b': domain = a.Parameter; break; case 'n': name = 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"); 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); p.start(bus); } 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 { directMsgRE = new Regex("^\\.direct ([^ ]*) ([0-9]+) (.*)"); } 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; looperThread = new Thread(new ThreadStart(Run)); looperThread.Name = "Keyboard Input Thread"; looperThread.Start(); } 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; parseCommand(s); } 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"); // crude parsing of the ".xyz" commands // TODO use regexps instends of String.lastIndexOf(String). Example // provided with .direct ! if (s.Length == 0) { println("-> Sent to " + bus.SendMsg(s) + " peers"); } else if ((result = directMsgRE.Match(s)).Success) { String target = result.Groups[1].ToString(); ushort id = ushort.Parse(result.Groups[2].ToString()); String message = result.Groups[3].ToString(); List 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); return ; } else if (s.LastIndexOf(".die ") >= 0) { String target = s.Substring(5); if (bus.Die(target, ".die command") == 0) println("no Ivy client with the name \"" + target + "\""); } else if (s.LastIndexOf(".unbind ") >= 0) { String regexp = s.Substring(8); if (bus.UnbindMsg(regexp)) { println("you want to unsubscribe to " + regexp); } else { println("you can't unsubscribe to " + regexp + ", your're not subscribed to it"); } } else if (s.LastIndexOf(".bind ") >= 0) { String regexp = s.Substring(6); println("you want to subscribe to " + regexp); bus.BindMsg(regexp, receive); } else if (s.LastIndexOf(".ping ") >= 0) { String target = s.Substring(6); if (bus.Ping( target, "test") == 0) { println("no Ivy client with the name \"" + target + "\""); } } else if ((s.LastIndexOf(".quit") >= 0) || (s.LastIndexOf(".bye") >= 0)) { bus.Stop(); System.Environment.Exit(0); } else if (s.LastIndexOf(".list") >= 0) { println(bus.IvyClients.Count + " clients on the bus"); foreach (IvyClient client in bus.IvyClients ) { println("-> " + client.ApplicationName); } } else if (s.LastIndexOf(".help") >= 0) { println(helpCommands); } else if (s[0] == '.') { println("this command is not recognized"); println(helpCommands); } else { println("-> Sent to " + bus.SendMsg(s) + " peers"); } } // parseCommand private void connect(object sender, IvyEventArgs e) { println(e.Client.ApplicationName + " connected from "+e.Client.RemoteAddress+":"+e.Client.RemotePort); foreach (string re in e.Client.Regexps ) { println(e.Client.ApplicationName + " subscribes to " + re); } } 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 "; // Copy the collection to a new array starting at index 0. String[] args = new String[e.Arguments.Count]; e.Arguments.CopyTo(args, 0); s += string.Join(",", args); println(s); } [Conditional("DEBUG")] private void traceDebug(String s) { Trace.WriteLineIf(debug, "-->Probe<-- " + s); } private void println(String s) { if (!quiet) System.Console.Out.WriteLine(date() + s); } private String date() { if (!timestamp) return ""; System.DateTime d = System.DateTime.Now; return "[" + d + "] "; } } }