LIBOMV-492 WinGridProxy - Automatically colorize packet details in view

* Log Viewer built into WinGridProxy
* New Decoder system supports the ability to do custom decoding on packet fields, PacketToString moved from Helpers to its own class.
* GridProxy library now uses log4net library to do logging, WinGridProxy logging configuration added to make use of this.
LIBOMV-512 WinGridProxy decodes KeyValue pairs

* Added Invert & Mirror flags to sculptType enum
* Converted SoundManager to use the SoundFlags enum in the AttachedSound callback
* TestClient "who" command now shows agents logal ID

git-svn-id: http://libopenmetaverse.googlecode.com/svn/libopenmetaverse/trunk@2805 52acb1d6-8a22-11de-b505-999d5b087335
This commit is contained in:
Jim Radford
2009-05-25 19:00:28 +00:00
parent 63552f5ea3
commit de8c3131a1
15 changed files with 1828 additions and 486 deletions

View File

@@ -30,7 +30,7 @@ using System.Net;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Text.RegularExpressions;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
@@ -43,6 +43,7 @@ using OpenMetaverse.StructuredData;
using OpenMetaverse.Interfaces;
using System.Xml;
using Nwc.XmlRpc;
using Logger=OpenMetaverse.Logger;
namespace WinGridProxy
{
@@ -56,6 +57,7 @@ namespace WinGridProxy
ProxyManager proxy;
private PacketDecoder DecodePacket = new PacketDecoder();
private int PacketCounter;
@@ -73,12 +75,18 @@ namespace WinGridProxy
{
InitializeComponent();
Logger.Log("WinGridProxy ready", Helpers.LogLevel.Info);
if (FireEventAppender.Instance != null)
{
FireEventAppender.Instance.MessageLoggedEvent += new MessageLoggedEventHandler(Instance_MessageLoggedEvent);
}
// populate the listen box with IPs
IPHostEntry iphostentry = Dns.GetHostByName(Dns.GetHostName());
foreach (IPAddress address in iphostentry.AddressList)
comboBoxListenAddress.Items.Add(address.ToString());
ProxyManager.OnPacketLog += ProxyManager_OnPacketLog;
ProxyManager.OnMessageLog += ProxyManager_OnMessageLog;
ProxyManager.OnLoginResponse += ProxyManager_OnLoginResponse;
@@ -956,7 +964,7 @@ namespace WinGridProxy
}
else
{
result.AppendFormat("{0, 30}: {1} ({2})" + System.Environment.NewLine,
result.AppendFormat("{0, 30}: {1} ({2})" + Environment.NewLine,
nestedField.Name,
nestedField.GetValue(nestedArrayObject),
nestedField.GetValue(nestedArrayObject).GetType().Name);
@@ -968,7 +976,7 @@ namespace WinGridProxy
{
if (messageField.FieldType.IsEnum)
{
result.AppendFormat("{0, 30}: {1} {2} ({3})" + System.Environment.NewLine,
result.AppendFormat("{0, 30}: {1} {2} ({3})" + Environment.NewLine,
messageField.Name,
Enum.Format(messageField.GetValue(message).GetType(),
messageField.GetValue(message), "D"),
@@ -989,159 +997,6 @@ namespace WinGridProxy
return result.ToString();
}
private static string InterpretOptions(Header header)
{
return "["
+ (header.AppendedAcks ? "Ack" : " ")
+ " "
+ (header.Resent ? "Res" : " ")
+ " "
+ (header.Reliable ? "Rel" : " ")
+ " "
+ (header.Zerocoded ? "Zer" : " ")
+ "]"
;
}
/// <summary>
/// Creates a formatted string containing the values of a Packet
/// </summary>
/// <param name="packet">The Packet</param>
/// <returns>A formatted string of values of the nested items in the Packet object</returns>
/// <remarks>TODO: This is overly complex. Static helpers should be created to clean this up and it
/// should be made generic enough to decode IMessage objects too.</remarks>
public static string PacketToString(Packet packet)
{
StringBuilder result = new StringBuilder();
result.AppendFormat("Packet Type: {0}" + System.Environment.NewLine, packet.Type);
result.AppendLine("[Packet Header]");
// payload
result.AppendFormat("Sequence: {0}" + System.Environment.NewLine, packet.Header.Sequence);
result.AppendFormat(" Options: {0}" + System.Environment.NewLine, InterpretOptions(packet.Header));
result.AppendLine();
result.AppendLine("[Packet Payload]");
foreach (FieldInfo packetField in packet.GetType().GetFields())
{
object packetDataObject = packetField.GetValue(packet);
result.AppendFormat("-- {0,20} --" + System.Environment.NewLine, packetField.Name);
foreach (FieldInfo packetValueField in packetField.GetValue(packet).GetType().GetFields())
{
result.AppendFormat("{0,30}: {1}" + System.Environment.NewLine,
packetValueField.Name, packetValueField.GetValue(packetDataObject));
}
// handle blocks that are arrays
if (packetDataObject.GetType().IsArray)
{
foreach (object nestedArrayRecord in packetDataObject as Array)
{
// handle properties
foreach (PropertyInfo propertyInfo in nestedArrayRecord.GetType().GetProperties())
{
if (propertyInfo.GetValue(nestedArrayRecord, null).GetType() == typeof(byte[]))
{
result.AppendFormat("{0, 30}: {1}" + Environment.NewLine,
propertyInfo.Name,
Utils.BytesToString((byte[])propertyInfo.GetValue(nestedArrayRecord, null)));
}
}
// handle fields
foreach (FieldInfo packetArrayField in nestedArrayRecord.GetType().GetFields())
{
if (packetArrayField.GetValue(nestedArrayRecord).GetType() == typeof(Byte[]))
{
result.AppendFormat("{0,30}: {1}" + Environment.NewLine,
packetArrayField.Name,
new Color4((byte[])packetArrayField.GetValue(nestedArrayRecord), 0, false));
}
else
{
result.AppendFormat("{0,30}: {1}" + Environment.NewLine,
packetArrayField.Name, packetArrayField.GetValue(nestedArrayRecord));
}
}
}
}
else
{
// handle non array data blocks
foreach (PropertyInfo packetPropertyField in packetField.GetValue(packet).GetType().GetProperties())
{
// Handle fields named "Data" specifically, this is generally binary data, we'll display it as hex values
if (packetPropertyField.PropertyType.Equals(typeof(Byte[]))
&& packetPropertyField.Name.Equals("Data"))
{
result.AppendFormat("{0}" + System.Environment.NewLine,
Utils.BytesToHexString((byte[])packetPropertyField.GetValue(packetDataObject, null),
packetPropertyField.Name));
}
// decode bytes into strings
else if (packetPropertyField.PropertyType.Equals(typeof(Byte[])))
{
// Handle TextureEntry fields specifically
if (packetPropertyField.Name.Equals("TextureEntry"))
{
byte[] tebytes = (byte[])packetPropertyField.GetValue(packetDataObject, null);
Primitive.TextureEntry te = new Primitive.TextureEntry(tebytes, 0, tebytes.Length);
result.AppendFormat("{0,30}:\n{1}", packetPropertyField.Name, te.ToString());
}
else
{
// Decode the BinaryBucket
if (packetPropertyField.Name.Equals("BinaryBucket"))
{
byte[] bytes = (byte[])packetPropertyField.GetValue(packetDataObject, null);
string bbDecoded = String.Empty;
if (bytes.Length == 1)
{
bbDecoded = String.Format("{0}", bytes[0]);
}
else if (bytes.Length == 17)
{
bbDecoded = String.Format("{0} {1} ({2})",
new UUID(bytes, 1),
bytes[0],
(AssetType)bytes[0]);
}
else
{
bbDecoded = Utils.BytesToString(bytes);
}
result.AppendFormat("{0,30}: {1}" + System.Environment.NewLine,
packetPropertyField.Name,
bbDecoded);
}
else
{
result.AppendFormat("{0,30}: {1}" + System.Environment.NewLine,
packetPropertyField.Name,
Utils.BytesToString((byte[])packetPropertyField.GetValue(packetDataObject, null)));
}
}
}
else
{
// this seems to be limited to the length property, since all others have been previously handled
if (packetPropertyField.Name != "Length")
{
result.AppendFormat("{0,30}: {1} [{2}]" + System.Environment.NewLine,
packetPropertyField.Name, packetPropertyField.GetValue(packetDataObject, null),
packetPropertyField.GetType());
}
}
}
}
}
return result.ToString();
}
private void SaveAllSettings(string fileName)
{
Store.MessageSessions.Clear();
@@ -1336,8 +1191,7 @@ namespace WinGridProxy
else if (tag is Packet)
{
Packet packet = (Packet)tag;
return PacketToString(packet);
return DecodePacket.PacketToString(packet);
}
else if (tag is CapsRequest)
{
@@ -1561,7 +1415,6 @@ namespace WinGridProxy
private void autoColorizeToolStripMenuItem_Click(object sender, EventArgs e)
{
if (colorDialog1.ShowDialog() == DialogResult.OK)
{
//listview.BackColor = colorDialog1.Color;
@@ -1573,5 +1426,59 @@ namespace WinGridProxy
FormPluginManager pluginManager = new FormPluginManager(proxy.Proxy);
pluginManager.ShowDialog();
}
void Instance_MessageLoggedEvent(object sender, MessageLoggedEventArgs e)
{
if(this.IsDisposed || this.Disposing)
return;
if (InvokeRequired)
{
BeginInvoke(new MethodInvoker(delegate()
{
Instance_MessageLoggedEvent(sender, e);
}));
}
else
{
string s = String.Format("{0} [{1}] {2} {3}", e.LoggingEvent.TimeStamp, e.LoggingEvent.Level,
e.LoggingEvent.RenderedMessage, e.LoggingEvent.ExceptionObject);
richTextBoxDebugLog.AppendText(s + "\n");
}
}
private void richTextBoxDecodedRequest_TextChanged(object sender, EventArgs e)
{
RichTextBox m_rtb = (RichTextBox) sender;
Regex typesRegex = new Regex(@"\[(?<Type>\w+|\w+\[\])\]|\((?<Enum>.*)\)|\s-- (?<Header>\w+|\w+ \[\]) --\s|(?<BlockSep>\s\*\*\*\s)|(?<Tag>\s<\w+>\s|\s<\/\w+>\s)|(?<BlockCounter>\s\w+\[\d+\]\s)", RegexOptions.ExplicitCapture);
MatchCollection matches = typesRegex.Matches(m_rtb.Text);
foreach(Match match in matches)
{
m_rtb.SelectionStart = match.Index +1;
m_rtb.SelectionLength = match.Length -2;
m_rtb.SelectionFont = new Font(m_rtb.Font.FontFamily, m_rtb.Font.Size, FontStyle.Bold);
if (!String.IsNullOrEmpty(match.Groups["Type"].Value))
m_rtb.SelectionColor = Color.Blue;
else if (!String.IsNullOrEmpty(match.Groups["Enum"].Value))
m_rtb.SelectionColor = Color.FromArgb(43, 145, 175);
else if (!String.IsNullOrEmpty(match.Groups["Header"].Value))
{
m_rtb.SelectionColor = Color.Green;
m_rtb.SelectionBackColor = Color.LightSteelBlue;
}
else if (!String.IsNullOrEmpty(match.Groups["BlockSep"].Value))
m_rtb.SelectionColor = Color.Gold;
else if (!String.IsNullOrEmpty(match.Groups["Tag"].Value))
{
m_rtb.SelectionColor = Color.White;
m_rtb.SelectionBackColor = Color.Black;
}
else if (!String.IsNullOrEmpty(match.Groups["BlockCounter"].Value))
m_rtb.SelectionColor = Color.Green;
}
}
}
}