diff --git a/Programs/GridProxy/GridProxy.cs b/Programs/GridProxy/GridProxy.cs index f7e8e85a..f28afbd3 100644 --- a/Programs/GridProxy/GridProxy.cs +++ b/Programs/GridProxy/GridProxy.cs @@ -370,9 +370,9 @@ namespace GridProxy Thread connThread = new Thread((ThreadStart)delegate { - OpenMetaverse.Logger.Log(">T> LoginProxy", Helpers.LogLevel.Debug); +// OpenMetaverse.Logger.Log(">T> LoginProxy", Helpers.LogLevel.Debug); ProxyHTTP(client); - OpenMetaverse.Logger.Log(" headers, byte[] content, int reqNo) { +// Console.WriteLine("ProxyCaps {0} {1}", meth, uri); Match match = new Regex(@"^(https?)://([^:/]+)(:\d+)?(/.*)$").Match(uri); if (!match.Success) { @@ -640,6 +641,9 @@ namespace GridProxy CapsRequest capReq = null; bool shortCircuit = false; bool requestFailed = false; if (cap != null) { +// if (cap.CapType != "GetTexture" && cap.CapType != "ViewerStats" && cap.CapType != "ViewerMetrics") +// Console.WriteLine("CAP request {0} {1}", meth, cap.CapType); + capReq = new CapsRequest(cap); if (cap.ReqFmt == CapsDataFormat.OSD) @@ -748,7 +752,7 @@ namespace GridProxy } else if (cap == null) { - OpenMetaverse.Logger.Log(string.Format("{0} {1}", req.Method, req.Address.ToString()), Helpers.LogLevel.Info); +// OpenMetaverse.Logger.Log(string.Format("{0} {1}", req.Method, req.Address.ToString()), Helpers.LogLevel.Info); } resp = (HttpWebResponse)req.GetResponse(); } @@ -879,8 +883,11 @@ namespace GridProxy } consoleMsg += "\n" + respString + "\n--------"; - OpenMetaverse.Logger.Log(consoleMsg, Helpers.LogLevel.Debug); - OpenMetaverse.Logger.Log("[" + reqNo + "] Fixed-up response:\n" + respString + "\n--------", Helpers.LogLevel.Debug); +// OpenMetaverse.Logger.Log(consoleMsg, Helpers.LogLevel.Debug); + +// if (cap.CapType == "FetchInventory2" || cap.CapType == "FetchInventoryDescendents2") + +// OpenMetaverse.Logger.Log("[" + reqNo + "] Fixed-up response:\n" + respString + "\n--------", Helpers.LogLevel.Debug); try { @@ -915,6 +922,8 @@ namespace GridProxy if (!String.IsNullOrEmpty(val)) { + OpenMetaverse.Logger.Log(string.Format("Got CAP {0}:{1}", key, val), Helpers.LogLevel.Debug); + if (!KnownCaps.ContainsKey(val)) { CapsDataFormat resFmt = BinaryResponseCaps.Contains(key) ? CapsDataFormat.Binary : CapsDataFormat.OSD; diff --git a/Programs/GridProxy/GridProxyMain.cs b/Programs/GridProxy/GridProxyMain.cs index 04430ca7..ad4c0e48 100644 --- a/Programs/GridProxy/GridProxyMain.cs +++ b/Programs/GridProxy/GridProxyMain.cs @@ -8,7 +8,9 @@ class ProxyMain { ProxyFrame p = new ProxyFrame(args); ProxyPlugin analyst = new Analyst(p); - analyst.Init(); + analyst.Init(); + ProxyPlugin capAnalyst = new CapAnalyst(p); + capAnalyst.Init(); p.proxy.Start(); } } \ No newline at end of file diff --git a/Programs/GridProxy/Plugins/CapAnalyst.cs b/Programs/GridProxy/Plugins/CapAnalyst.cs new file mode 100644 index 00000000..d02fff0e --- /dev/null +++ b/Programs/GridProxy/Plugins/CapAnalyst.cs @@ -0,0 +1,875 @@ +/* + * Analyst.cs: proxy that makes packet inspection and modifcation interactive + * See the README for usage instructions. + * + * Copyright (c) 2006 Austin Jennings + * Modified by "qode" and "mcortez" on December 21st, 2006 to work with the new + * pregen + * All rights reserved. + * + * - Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * - Neither the name of the openmetaverse.org nor the names + * of its contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +using System; +using System.Collections; +using System.Collections.Generic; +using System.Globalization; +using System.IO; +using System.Net; +using System.Text.RegularExpressions; +using System.Reflection; +using System.Xml; +using Nwc.XmlRpc; +using OpenMetaverse; +using OpenMetaverse.StructuredData; +using OpenMetaverse.Packets; +using GridProxy; + + +public class CapAnalyst : ProxyPlugin +{ + private ProxyFrame frame; + private Proxy proxy; + private HashSet loggedCaps = new HashSet(); + private string logGrep = null; + private Dictionary> modifiedPackets = new Dictionary>(); + private Assembly openmvAssembly; + private StreamWriter output; + + //private PacketDecoder DecodePacket = new PacketDecoder(); + + public CapAnalyst(ProxyFrame frame) + { + this.frame = frame; + this.proxy = frame.proxy; + } + + ~CapAnalyst() + { + if (output != null) + output.Close(); + } + + public override void Init() + { + openmvAssembly = Assembly.Load("OpenMetaverse"); + if (openmvAssembly == null) throw new Exception("Assembly load exception"); + + // build the table of /command delegates + InitializeCommandDelegates(); + + // handle command line arguments + foreach (string arg in frame.Args) + if (arg == "--log-all") + LogAll(); + else if (arg.Contains("--log-whitelist=")) + LogWhitelist(arg.Substring(arg.IndexOf('=') + 1)); + else if (arg.Contains("--no-log-blacklist=")) + NoLogBlacklist(arg.Substring(arg.IndexOf('=') + 1)); + else if (arg.Contains("--output=")) + SetOutput(arg.Substring(arg.IndexOf('=') + 1)); + + StartLogCap("FetchInventory2"); + StartLogCap("FetchInventoryDescendents2"); + + Console.WriteLine("CapAnalyst loaded"); + } + + // InitializeCommandDelegates: configure Analyst's commands + private void InitializeCommandDelegates() + { + frame.AddCommand("/logcap", new ProxyFrame.CommandDelegate(CmdLog)); + frame.AddCommand("/-logcap", new ProxyFrame.CommandDelegate(CmdNoLog)); +// frame.AddCommand("/grep", new ProxyFrame.CommandDelegate(CmdGrep)); +// frame.AddCommand("/drop", new ProxyFrame.CommandDelegate(CmdDrop)); +// frame.AddCommand("/-drop", new ProxyFrame.CommandDelegate(CmdNoDrop)); +// frame.AddCommand("/set", new ProxyFrame.CommandDelegate(CmdSet)); +// frame.AddCommand("/-set", new ProxyFrame.CommandDelegate(CmdNoSet)); +// frame.AddCommand("/inject", new ProxyFrame.CommandDelegate(CmdInject)); +// frame.AddCommand("/in", new ProxyFrame.CommandDelegate(CmdInject)); + } + +// private static PacketType packetTypeFromName(string name) +// { +// Type packetTypeType = typeof(PacketType); +// System.Reflection.FieldInfo f = packetTypeType.GetField(name); +// if (f == null) throw new ArgumentException("Bad packet type"); +// return (PacketType)Enum.ToObject(packetTypeType, (int)f.GetValue(packetTypeType)); +// } + + // CmdLog: handle a /log command + private void CmdLog(string[] words) + { + if (words.Length != 2) + SayToUser("Usage: /logcap "); + else if (words[1] == "*") + { + LogAll(); + SayToUser("logging all caps"); + } + else + { +// PacketType pType; +// try +// { +// pType = packetTypeFromName(words[1]); +// } +// catch (ArgumentException) +// { +// SayToUser("Bad cap name: " + words[1]); +// return; +// } + string capName = words[1]; + + StartLogCap(capName); + SayToUser("logging " + capName); + } + } + + private void StartLogCap(string capName) + { + loggedCaps.Add(capName); + proxy.AddCapsDelegate(capName, LogCap); + } + + // CmdNoLog: handle a /-log command + private void CmdNoLog(string[] words) + { + if (words.Length != 2) + SayToUser("Usage: /-logcap "); + else if (words[1] == "*") + { + NoLogAll(); + SayToUser("stopped logging all caps"); + } + else + { +// PacketType pType = packetTypeFromName(words[1]); + string capName = words[1]; + loggedCaps.Remove(capName); + proxy.RemoveCapRequestDelegate(capName, LogCap); + + SayToUser("stopped logging " + capName); + } + } + + // CmdGrep: handle a /grep command + private void CmdGrep(string[] words) + { + if (words.Length == 1) + { + logGrep = null; + SayToUser("stopped filtering logs"); + } + else + { + string[] regexArray = new string[words.Length - 1]; + Array.Copy(words, 1, regexArray, 0, words.Length - 1); + logGrep = String.Join(" ", regexArray); + SayToUser("filtering log with " + logGrep); + } + } + + private void CmdDrop(string[] words) + { + throw new NotImplementedException(); + } + + private void CmdNoDrop(string[] words) + { + throw new NotImplementedException(); + } + + // CmdSet: handle a /set command + private void CmdSet(string[] words) + { +// if (words.Length < 5) +// SayToUser("Usage: /set "); +// else +// { +// PacketType pType; +// try +// { +// pType = packetTypeFromName(words[1]); +// } +// catch (ArgumentException) +// { +// SayToUser("Bad packet name: " + words[1]); +// return; +// } +// +// string[] valueArray = new string[words.Length - 4]; +// Array.Copy(words, 4, valueArray, 0, words.Length - 4); +// string valueString = String.Join(" ", valueArray); +// object value; +// try +// { +// value = MagicCast(words[1], words[2], words[3], valueString); +// } +// catch (Exception e) +// { +// SayToUser(e.Message); +// return; +// } +// +// Dictionary fields; +// if (modifiedPackets.ContainsKey(pType)) +// fields = (Dictionary)modifiedPackets[pType]; +// else +// fields = new Dictionary(); +// +// fields[new BlockField(words[2], words[3])] = value; +// modifiedPackets[pType] = fields; +// +// proxy.AddDelegate(pType, Direction.Incoming, new PacketDelegate(ModifyIn)); +// proxy.AddDelegate(pType, Direction.Outgoing, new PacketDelegate(ModifyOut)); +// +// SayToUser("setting " + words[1] + "." + words[2] + "." + words[3] + " = " + valueString); +// } + } + + // CmdNoSet: handle a /-set command + private void CmdNoSet(string[] words) + { +// if (words.Length == 2 && words[1] == "*") +// { +// foreach (PacketType pType in modifiedPackets.Keys) +// { +// proxy.RemoveDelegate(pType, Direction.Incoming, new PacketDelegate(ModifyIn)); +// proxy.RemoveDelegate(pType, Direction.Outgoing, new PacketDelegate(ModifyOut)); +// } +// modifiedPackets = new Dictionary>(); +// +// SayToUser("stopped setting all fields"); +// } +// else if (words.Length == 4) +// { +// PacketType pType; +// try +// { +// pType = packetTypeFromName(words[1]); +// } +// catch (ArgumentException) +// { +// SayToUser("Bad packet name: " + words[1]); +// return; +// } +// +// +// if (modifiedPackets.ContainsKey(pType)) +// { +// Dictionary fields = modifiedPackets[pType]; +// fields.Remove(new BlockField(words[2], words[3])); +// +// if (fields.Count == 0) +// { +// modifiedPackets.Remove(pType); +// +// proxy.RemoveDelegate(pType, Direction.Incoming, new PacketDelegate(ModifyIn)); +// proxy.RemoveDelegate(pType, Direction.Outgoing, new PacketDelegate(ModifyOut)); +// } +// } +// +// SayToUser("stopped setting " + words[1] + "." + words[2] + "." + words[3]); +// } +// else +// SayToUser("Usage: /-set "); + } + + + // CmdInject: handle an /inject command + private void CmdInject(string[] words) + { +// if (words.Length < 2) +// SayToUser("Usage: /inject [value]"); +// else +// { +// string[] valueArray = new string[words.Length - 2]; +// Array.Copy(words, 2, valueArray, 0, words.Length - 2); +// string value = String.Join(" ", valueArray); +// +// FileStream fs = null; +// StreamReader sr = null; +// Direction direction = Direction.Incoming; +// string name = null; +// string block = null; +// object blockObj = null; +// Type packetClass = null; +// Packet packet = null; +// +// try +// { +// fs = File.OpenRead(words[1] + ".packet"); +// sr = new StreamReader(fs); +// +// string line; +// while ((line = sr.ReadLine()) != null) +// { +// Match match; +// +// if (name == null) +// { +// match = (new Regex(@"^\s*(in|out)\s+(\w+)\s*$")).Match(line); +// if (!match.Success) +// { +// SayToUser("expecting direction and packet name, got: " + line); +// return; +// } +// +// string lineDir = match.Groups[1].Captures[0].ToString(); +// string lineName = match.Groups[2].Captures[0].ToString(); +// +// if (lineDir == "in") +// direction = Direction.Incoming; +// else if (lineDir == "out") +// direction = Direction.Outgoing; +// else +// { +// SayToUser("expecting 'in' or 'out', got: " + line); +// return; +// } +// +// name = lineName; +// packetClass = openmvAssembly.GetType("OpenMetaverse.Packets." + name + "Packet"); +// if (packetClass == null) throw new Exception("Couldn't get class " + name + "Packet"); +// ConstructorInfo ctr = packetClass.GetConstructor(new Type[] { }); +// if (ctr == null) throw new Exception("Couldn't get suitable constructor for " + name + "Packet"); +// packet = (Packet)ctr.Invoke(new object[] { }); +// //Console.WriteLine("Created new " + name + "Packet"); +// } +// else +// { +// match = (new Regex(@"^\s*\[(\w+)\]\s*$")).Match(line); +// if (match.Success) +// { +// block = match.Groups[1].Captures[0].ToString(); +// FieldInfo blockField = packetClass.GetField(block); +// if (blockField == null) throw new Exception("Couldn't get " + name + "Packet." + block); +// Type blockClass = blockField.FieldType; +// if (blockClass.IsArray) +// { +// blockClass = blockClass.GetElementType(); +// ConstructorInfo ctr = blockClass.GetConstructor(new Type[] { }); +// if (ctr == null) throw new Exception("Couldn't get suitable constructor for " + blockClass.Name); +// blockObj = ctr.Invoke(new object[] { }); +// object[] arr = (object[])blockField.GetValue(packet); +// object[] narr = (object[])Array.CreateInstance(blockClass, arr.Length + 1); +// Array.Copy(arr, narr, arr.Length); +// narr[arr.Length] = blockObj; +// blockField.SetValue(packet, narr); +// //Console.WriteLine("Added block "+block); +// } +// else +// { +// blockObj = blockField.GetValue(packet); +// } +// if (blockObj == null) throw new Exception("Got " + name + "Packet." + block + " == null"); +// //Console.WriteLine("Got block " + name + "Packet." + block); +// +// continue; +// } +// +// if (block == null) +// { +// SayToUser("expecting block name, got: " + line); +// return; +// } +// +// match = (new Regex(@"^\s*(\w+)\s*=\s*(.*)$")).Match(line); +// if (match.Success) +// { +// string lineField = match.Groups[1].Captures[0].ToString(); +// string lineValue = match.Groups[2].Captures[0].ToString(); +// object fval; +// +// //FIXME: use of MagicCast inefficient +// if (lineValue == "$Value") +// fval = MagicCast(name, block, lineField, value); +// else if (lineValue == "$UUID") +// fval = UUID.Random(); +// else if (lineValue == "$AgentID") +// fval = frame.AgentID; +// else if (lineValue == "$SessionID") +// fval = frame.SessionID; +// else +// fval = MagicCast(name, block, lineField, lineValue); +// +// MagicSetField(blockObj, lineField, fval); +// continue; +// } +// +// SayToUser("expecting block name or field, got: " + line); +// return; +// } +// } +// +// if (name == null) +// { +// SayToUser("expecting direction and packet name, got EOF"); +// return; +// } +// +// packet.Header.Reliable = true; +// //if (protocolManager.Command(name).Encoded) +// // packet.Header.Zerocoded = true; +// proxy.InjectPacket(packet, direction); +// +// SayToUser("injected " + words[1]); +// } +// catch (Exception e) +// { +// SayToUser("failed to inject " + words[1] + ": " + e.Message); +// Console.WriteLine("failed to inject " + words[1] + ": " + e.Message + "\n" + e.StackTrace); +// } +// finally +// { +// if (fs != null) +// fs.Close(); +// if (sr != null) +// sr.Close(); +// } +// } + } + + // SayToUser: send a message to the user as in-world chat + private void SayToUser(string message) + { + ChatFromSimulatorPacket packet = new ChatFromSimulatorPacket(); + packet.ChatData.FromName = Utils.StringToBytes("Analyst"); + packet.ChatData.SourceID = UUID.Random(); + packet.ChatData.OwnerID = frame.AgentID; + packet.ChatData.SourceType = (byte)2; + packet.ChatData.ChatType = (byte)1; + packet.ChatData.Audible = (byte)1; + packet.ChatData.Position = new Vector3(0, 0, 0); + packet.ChatData.Message = Utils.StringToBytes(message); + proxy.InjectPacket(packet, Direction.Incoming); + } + + // BlockField: product type for a block name and field name + private struct BlockField + { + public string block; + public string field; + + + public BlockField(string block, string field) + { + this.block = block; + this.field = field; + } + } + + private static void MagicSetField(object obj, string field, object val) + { + Type cls = obj.GetType(); + + FieldInfo fieldInf = cls.GetField(field); + if (fieldInf == null) + { + PropertyInfo prop = cls.GetProperty(field); + if (prop == null) throw new Exception("Couldn't find field " + cls.Name + "." + field); + prop.SetValue(obj, val, null); + //throw new Exception("FIXME: can't set properties"); + } + else + { + fieldInf.SetValue(obj, val); + } + } + + // MagicCast: given a packet/block/field name and a string, convert the string to a value of the appropriate type + private object MagicCast(string name, string block, string field, string value) + { + Type packetClass = openmvAssembly.GetType("OpenMetaverse.Packets." + name + "Packet"); + if (packetClass == null) throw new Exception("Couldn't get class " + name + "Packet"); + + FieldInfo blockField = packetClass.GetField(block); + if (blockField == null) throw new Exception("Couldn't get " + name + "Packet." + block); + Type blockClass = blockField.FieldType; + if (blockClass.IsArray) blockClass = blockClass.GetElementType(); + // Console.WriteLine("DEBUG: " + blockClass.Name); + + FieldInfo fieldField = blockClass.GetField(field); PropertyInfo fieldProp = null; + Type fieldClass = null; + if (fieldField == null) + { + fieldProp = blockClass.GetProperty(field); + if (fieldProp == null) throw new Exception("Couldn't get " + name + "Packet." + block + "." + field); + fieldClass = fieldProp.PropertyType; + } + else + { + fieldClass = fieldField.FieldType; + } + + try + { + if (fieldClass == typeof(byte)) + { + return Convert.ToByte(value); + } + else if (fieldClass == typeof(ushort)) + { + return Convert.ToUInt16(value); + } + else if (fieldClass == typeof(uint)) + { + return Convert.ToUInt32(value); + } + else if (fieldClass == typeof(ulong)) + { + return Convert.ToUInt64(value); + } + else if (fieldClass == typeof(sbyte)) + { + return Convert.ToSByte(value); + } + else if (fieldClass == typeof(short)) + { + return Convert.ToInt16(value); + } + else if (fieldClass == typeof(int)) + { + return Convert.ToInt32(value); + } + else if (fieldClass == typeof(long)) + { + return Convert.ToInt64(value); + } + else if (fieldClass == typeof(float)) + { + return Convert.ToSingle(value); + } + else if (fieldClass == typeof(double)) + { + return Convert.ToDouble(value); + } + else if (fieldClass == typeof(UUID)) + { + return new UUID(value); + } + else if (fieldClass == typeof(bool)) + { + if (value.ToLower() == "true") + return true; + else if (value.ToLower() == "false") + return false; + else + throw new Exception(); + } + else if (fieldClass == typeof(byte[])) + { + return Utils.StringToBytes(value); + } + else if (fieldClass == typeof(Vector3)) + { + Vector3 result; + if (Vector3.TryParse(value, out result)) + return result; + else + throw new Exception(); + } + else if (fieldClass == typeof(Vector3d)) + { + Vector3d result; + if (Vector3d.TryParse(value, out result)) + return result; + else + throw new Exception(); + } + else if (fieldClass == typeof(Vector4)) + { + Vector4 result; + if (Vector4.TryParse(value, out result)) + return result; + else + throw new Exception(); + } + else if (fieldClass == typeof(Quaternion)) + { + Quaternion result; + if (Quaternion.TryParse(value, out result)) + return result; + else + throw new Exception(); + } + else + { + throw new Exception("unsupported field type " + fieldClass); + } + } + catch + { + throw new Exception("unable to interpret " + value + " as " + fieldClass); + } + } + + // ModifyIn: modify an incoming packet + private Packet ModifyIn(Packet packet, IPEndPoint endPoint) + { + return Modify(packet, endPoint, Direction.Incoming); + } + + // ModifyOut: modify an outgoing packet + private Packet ModifyOut(Packet packet, IPEndPoint endPoint) + { + return Modify(packet, endPoint, Direction.Outgoing); + } + + // Modify: modify a packet + private Packet Modify(Packet packet, IPEndPoint endPoint, Direction direction) + { + if (modifiedPackets.ContainsKey(packet.Type)) + { + try + { + Dictionary changes = modifiedPackets[packet.Type]; + Type packetClass = packet.GetType(); + + foreach (KeyValuePair change in changes) + { + BlockField bf = change.Key; + FieldInfo blockField = packetClass.GetField(bf.block); + if (blockField.FieldType.IsArray) // We're modifying a variable block. + { + // Modify each block in the variable block identically. + // This is really simple, can probably be improved. + object[] blockArray = (object[])blockField.GetValue(packet); + foreach (object blockElement in blockArray) + { + MagicSetField(blockElement, bf.field, change.Value); + } + } + else + { + //Type blockClass = blockField.FieldType; + object blockObject = blockField.GetValue(packet); + MagicSetField(blockObject, bf.field, change.Value); + } + } + } + catch (Exception e) + { + Console.WriteLine("failed to modify " + packet.Type + ": " + e.Message); + Console.WriteLine(e.StackTrace); + } + } + + return packet; + } + + // LogAll: register logging delegates for all packets + private void LogAll() + { +// Type packetTypeType = typeof(PacketType); +// System.Reflection.MemberInfo[] packetTypes = packetTypeType.GetMembers(); +// +// for (int i = 0; i < packetTypes.Length; i++) +// { +// if (packetTypes[i].MemberType == System.Reflection.MemberTypes.Field && packetTypes[i].DeclaringType == packetTypeType) +// { +// string name = packetTypes[i].Name; +// PacketType pType; +// +// try +// { +// pType = packetTypeFromName(name); +// } +// catch (Exception) +// { +// continue; +// } +// +// loggedCaps[pType] = null; +// +// proxy.AddDelegate(pType, Direction.Incoming, new PacketDelegate(LogPacketIn)); +// proxy.AddDelegate(pType, Direction.Outgoing, new PacketDelegate(LogPacketOut)); +// } +// } + } + + private void LogWhitelist(string whitelistFile) + { +// try +// { +// string[] lines = File.ReadAllLines(whitelistFile); +// int count = 0; +// +// for (int i = 0; i < lines.Length; i++) +// { +// string line = lines[i].Trim(); +// if (line.Length == 0) +// continue; +// +// PacketType pType; +// +// try +// { +// pType = packetTypeFromName(line); +// proxy.AddDelegate(pType, Direction.Incoming, new PacketDelegate(LogPacketIn)); +// proxy.AddDelegate(pType, Direction.Outgoing, new PacketDelegate(LogPacketOut)); +// ++count; +// } +// catch (ArgumentException) +// { +// Console.WriteLine("Bad packet name: " + line); +// } +// } +// +// Console.WriteLine(String.Format("Logging {0} packet types loaded from whitelist", count)); +// } +// catch (Exception) +// { +// Console.WriteLine("Failed to load packet whitelist from " + whitelistFile); +// } + } + + private void NoLogBlacklist(string blacklistFile) + { +// try +// { +// string[] lines = File.ReadAllLines(blacklistFile); +// int count = 0; +// +// for (int i = 0; i < lines.Length; i++) +// { +// string line = lines[i].Trim(); +// if (line.Length == 0) +// continue; +// +// PacketType pType; +// +// try +// { +// pType = packetTypeFromName(line); +// string[] noLogStr = new string[] {"/-log", line}; +// CmdNoLog(noLogStr); +// ++count; +// } +// catch (ArgumentException) +// { +// Console.WriteLine("Bad packet name: " + line); +// } +// } +// +// Console.WriteLine(String.Format("Not logging {0} packet types loaded from blacklist", count)); +// } +// catch (Exception) +// { +// Console.WriteLine("Failed to load packet blacklist from " + blacklistFile); +// } + } + + private void SetOutput(string outputFile) + { + try + { + output = new StreamWriter(outputFile, false); + Console.WriteLine("Logging packets to " + outputFile); + } + catch (Exception) + { + Console.WriteLine(String.Format("Failed to open {0} for logging", outputFile)); + } + } + + // NoLogAll: unregister logging delegates for all packets + private void NoLogAll() + { +// Type packetTypeType = typeof(PacketType); +// System.Reflection.MemberInfo[] packetTypes = packetTypeType.GetMembers(); +// +// for (int i = 0; i < packetTypes.Length; i++) +// { +// if (packetTypes[i].MemberType == System.Reflection.MemberTypes.Field && packetTypes[i].DeclaringType == packetTypeType) +// { +// string name = packetTypes[i].Name; +// PacketType pType; +// +// try +// { +// pType = packetTypeFromName(name); +// } +// catch (Exception) +// { +// continue; +// } +// +// loggedCaps.Remove(pType); +// +// proxy.RemoveDelegate(pType, Direction.Incoming, new PacketDelegate(LogPacketIn)); +// proxy.RemoveDelegate(pType, Direction.Outgoing, new PacketDelegate(LogPacketOut)); +// } +// } + } + + private bool LogCap(CapsRequest req, CapsStage stage) + { + if (stage == CapsStage.Request) + return false; + + using (StringWriter sw = new StringWriter()) + { + using (XmlTextWriter xtw = new XmlTextWriter(sw)) + { + xtw.Formatting = Formatting.Indented; + OSDParser.SerializeLLSDXmlElement(xtw, req.Request); + } + + Console.WriteLine("REQUEST {0}", req.Info.CapType); + Console.WriteLine(sw.ToString()); + } + + using (StringWriter sw = new StringWriter()) + { + using (XmlTextWriter xtw = new XmlTextWriter(sw)) + { + xtw.Formatting = Formatting.Indented; + OSDParser.SerializeLLSDXmlElement(xtw, req.Response); + } + + Console.WriteLine("RESPONSE {0}", req.Info.CapType); + Console.WriteLine(sw.ToString()); + } + + Console.WriteLine("------------------------------"); + + // We don't want to stop any other delegates from executing. + return false; + } + + // InterpretOptions: produce a string representing a packet's header options + private static string InterpretOptions(Header header) + { + return "[" + + (header.AppendedAcks ? "Ack" : " ") + + " " + + (header.Resent ? "Res" : " ") + + " " + + (header.Reliable ? "Rel" : " ") + + " " + + (header.Zerocoded ? "Zer" : " ") + + "]" + ; + } +} \ No newline at end of file