/// François-Régis Colin
/// http://www.tls.cena.fr/products/ivy/
/// *
/// (C) CENA
/// *
namespace IvyProbe
{
using System;
using System.Collections;
using System.Threading;
using System.Text.RegularExpressions;
using System.IO;
using System.Configuration;
using IvyBus;
/// Console implementation of the ivyprobe test program.
///
/// Mainly used for testing and debugging purpose
public class IvyProbe
{
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;
if ( ConfigurationSettings.AppSettings["domain"] != null )
domain = ConfigurationSettings.AppSettings["domain"];
if ( ConfigurationSettings.AppSettings["name"] != null )
name = ConfigurationSettings.AppSettings["name"];
if ( ConfigurationSettings.AppSettings["quiet"] != null )
quiet = bool.Parse(ConfigurationSettings.AppSettings["quiet"]);
if ( ConfigurationSettings.AppSettings["timestamp"] != null )
timestamp = bool.Parse(ConfigurationSettings.AppSettings["timestamp"]);
if ( ConfigurationSettings.AppSettings["IVY_DEBUG"] != null )
debug = bool.Parse(ConfigurationSettings.AppSettings["IVY_DEBUG"] );
/*
Getopt opt = new Getopt("Probe", args, "n:b:dqht");
int c;
while ((c = opt.getopt()) != - 1)
{
switch (c)
{
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 = opt.Optarg; break;
case 'n':
name = opt.Optarg; break;
case 'q':
quiet = true; break;
case 't':
timestamp = true; break;
case 'h': default:
System.Console.Out.WriteLine(helpmsg);
System.Environment.Exit(0);
break;
}
}
*/
IvyProbe p = new IvyProbe(System.Console.In, timestamp, quiet, debug );
p.ExitOnDie = true;
Ivy bus = new Ivy(name, name + " ready");
/* for (int i = opt.Optind; i < args.Length; i++)
{
if (!quiet)
System.Console.Out.WriteLine("you want to subscribe to " + args[i]);
bus.bindMsg(args[i], p);
}
*/
if (!quiet)
System.Console.Out.WriteLine(bus.domains(domain));
bus.start(domain);
p.start(bus);
}
public IvyProbe(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 += new Ivy.ClientConnectedHandler( connect );
bus.clientDisconnected += new Ivy.ClientDisconnectedHandler( disconnect );
bus.dieReceived += new Ivy.DieHandler( die );
bus.directMessageReceived += new Ivy.DirectMessageHandler( 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();
int id = Int32.Parse(result.Groups[2].ToString());
String message = result.Groups[3].ToString();
ArrayList v = bus.getIvyClientsByName(target);
if (v.Count == 0)
println("no Ivy client with the name \"" + target + "\"");
for (int i = 0; i < v.Count; i++)
((IvyClient) v[i]).sendDirectMsg(id, message);
return ;
}
else if (s.LastIndexOf(".die ") >= 0)
{
String target = s.Substring(5);
System.Collections.ArrayList v = bus.getIvyClientsByName(target);
if (v.Count == 0)
println("no Ivy client with the name \"" + target + "\"");
for (int i = 0; i < v.Count; i++)
((IvyClient) v[i]).sendDie();
}
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, new Ivy.MessageHandler(receive));
}
else if (s.LastIndexOf(".ping ") >= 0)
{
String target = s.Substring(6);
ArrayList v = bus.getIvyClientsByName(target);
if (v.Count == 0)
{
println("no Ivy client with the name \"" + target + "\"");
}
for (int i = 0; i < v.Count; i++)
{
((IvyClient) v[i]).sendPing("test");
}
}
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.Values )
{
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(IvyClient client)
{
println(client.ApplicationName + " connected from "+client.RemoteAddress+":"+client.RemotePort);
foreach (string re in client.Regexps )
{
println(client.ApplicationName + " subscribes to " + re);
}
}
private void disconnect(IvyClient client)
{
println(client.ApplicationName + " disconnected ");
}
private bool die(IvyClient client, int id)
{
println("received die msg from " + client.ApplicationName + " good bye");
/* I cannot stop the readLine(), because it is native code */
if (exitOnDie)
System.Environment.Exit(0);
return true;
}
private void directMessage(IvyClient client, int id, String arg)
{
println(client.ApplicationName + " direct Message " + id + arg);
}
private void receive(IvyClient client, String[] args)
{
String s = client.ApplicationName + " sent";
for (int i = 0; i < args.Length; i++)
s += " '" + args[i] + "'";
println(s);
}
private void traceDebug(String s)
{
if (debug)
System.Console.Out.WriteLine("-->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 + "] ";
}
}
}