corrade-vassal – Rev 1

Subversion Repositories:
Rev:
/*
 * Copyright (c) 2006-2014, openmetaverse.org
 * 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.Net;
using System.Text;
using System.Reflection;
using OpenMetaverse;
using OpenMetaverse.Packets;
using OpenMetaverse.Messages;
using OpenMetaverse.StructuredData;
using OpenMetaverse.Interfaces;
using GridProxy;

namespace WinGridProxy
{
    #region Base Class
    internal abstract class Session
    {
        internal const string EmptyXml = "<?xml version=\"1.0\"?><Empty>XML representation of this item is not available.</Empty>";
        internal const string EmptyString = "String representation of this item is not available.";
        internal const string EmptyNotation = "Notation representation of this item is not available.";

        public Direction Direction { get; set; }
        public String Host { get; set; }
        public String Protocol { get; set; }
        public String Name { get; set; }
        public String ContentType { get; set; }
        public int Length { get; set; }
        public DateTime TimeStamp { get; set; }

        // listview specific stuff, not serialized or deserialized
        public bool Selected { get; set; }        
        public System.Drawing.Color BackColor { get; set; }

        public Session()
        {
            this.TimeStamp = DateTime.UtcNow;
            this.Host = this.Protocol = this.Name = String.Empty;
            this.Length = 0;
            this.ContentType = String.Empty;
        }

        public virtual string ToRawString(Direction direction)
        {
            return EmptyString;
        }

        public virtual byte[] ToBytes(Direction direction)
        {
            return OpenMetaverse.Utils.EmptyBytes;
        }

        public virtual string ToXml(Direction direction)
        {
            return EmptyXml;
        }

        public virtual string ToStringNotation(Direction direction)
        {
            return EmptyNotation;
        }

        public abstract string ToPrettyString(Direction direction);
        public abstract byte[] Serialize();
        public abstract Session Deserialize(byte[] bytes);
    }
    #endregion

    #region Packets
    internal sealed class SessionPacket : Session
    {
        public Packet Packet { get; set; }

        public SessionPacket() : base() { this.Protocol = "UDP"; }
        public SessionPacket(Packet packet, Direction direction, IPEndPoint endpoint, String contentType)
            : base()
        {
            this.Packet = packet;
            this.Name = packet.Type.ToString();
            this.Direction = direction;
            this.Host = String.Format("{0}:{1}", endpoint.Address, endpoint.Port);
            this.ContentType = contentType;
            this.Length = packet.Length;
            this.Protocol = "UDP";
        }

        public override string ToPrettyString(Direction direction)
        {
            if (direction == this.Direction)
                return PacketDecoder.PacketToString(this.Packet);
            else
                return String.Empty;
        }

        public override string ToRawString(Direction direction)
        {
            if (direction == this.Direction)
                return PacketDecoder.PacketToString(this.Packet);
            else
                return String.Empty;
        }

        public override byte[] ToBytes(Direction direction)
        {
            if (direction == this.Direction)
                return Packet.ToBytes();
            else
                return base.ToBytes(direction);
        }

        //public override string ToXml(Direction direction)
        //{
        //    if (direction == this.Direction)
        //        return Packet.ToXmlString(this.Packet);
        //    else
        //        return base.ToXml(direction);
        //}

        //public override string ToStringNotation(Direction direction)
        //{
        //    if (direction == this.Direction)
        //        return Packet.GetLLSD(this.Packet).ToString();
        //    else
        //        return base.ToStringNotation(direction);
        //}

        public override byte[] Serialize()
        {
            OSDMap map = new OSDMap(5);
            map["Name"] = OSD.FromString(this.Name);
            map["Host"] = OSD.FromString(this.Host);
            map["PacketBytes"] = OSD.FromBinary(this.Packet.ToBytes());
            map["Direction"] = OSD.FromInteger((int)this.Direction);
            map["ContentType"] = OSD.FromString(this.ContentType);

            return OpenMetaverse.Utils.StringToBytes(map.ToString());
        }

        public override Session Deserialize(byte[] bytes)
        {
            OSDMap map = (OSDMap)OSDParser.DeserializeLLSDNotation(OpenMetaverse.Utils.BytesToString(bytes));

            this.Host = map["Host"].AsString();
            this.Direction = (Direction)map["Direction"].AsInteger();
            this.ContentType = map["ContentType"].AsString();

            byte[] packetData = map["PacketBytes"].AsBinary();
            this.Length = packetData.Length;

            int packetEnd = packetData.Length - 1;
            this.Packet = Packet.BuildPacket(packetData, ref packetEnd, null);
            this.Name = this.Packet.Type.ToString();
            return this;
        }
    }
    #endregion Packets

    #region Capabilities
    internal sealed class SessionCaps : Session
    {
        byte[] RequestBytes { get; set; }
        byte[] ResponseBytes { get; set; }
        WebHeaderCollection RequestHeaders { get; set; }
        WebHeaderCollection ResponseHeaders { get; set; }
        string FullUri { get; set; }

        public SessionCaps() : base() { /*this.Protocol = "Caps";*/ }
        public SessionCaps(byte[] requestBytes, byte[] responseBytes,
            WebHeaderCollection requestHeaders, WebHeaderCollection responseHeaders,
            Direction direction, string uri, string capsKey, String proto, string fullUri)
            : base()
        {
            if (requestBytes != null)
                this.RequestBytes = requestBytes;
            else
                this.RequestBytes = OpenMetaverse.Utils.EmptyBytes;

            if (responseBytes != null)
                this.ResponseBytes = responseBytes;
            else
                this.ResponseBytes = OpenMetaverse.Utils.EmptyBytes;
            this.RequestHeaders = requestHeaders;
            this.ResponseHeaders = responseHeaders;
            this.Protocol = proto;
            this.FullUri = fullUri;

            this.Name = capsKey;
            this.Direction = direction;
            this.Host = uri;
            this.ContentType = (direction == Direction.Incoming) ? this.ResponseHeaders.Get("Content-Type") : this.RequestHeaders.Get("Content-Type");
            this.Length = (requestBytes != null) ? requestBytes.Length : 0;
            this.Length += (responseBytes != null) ? responseBytes.Length : 0;
        }

        public override string ToPrettyString(Direction direction)
        {
            try
            {
                if (direction == Direction.Incoming)
                {
                    if (this.ResponseBytes != null && this.ResponseBytes.Length > 0)
                    {
                        IMessage message = null;
                        OSD osd = OSDParser.Deserialize(this.ResponseBytes);

                        if (osd is OSDMap)
                        {
                            OSDMap data = (OSDMap)osd;

                            if (data.ContainsKey("body"))
                                message = OpenMetaverse.Messages.MessageUtils.DecodeEvent(this.Name, (OSDMap)data["body"]);
                            else
                                message = OpenMetaverse.Messages.MessageUtils.DecodeEvent(this.Name, data);

                            if (message != null)
                                return PacketDecoder.MessageToString(message, 0);
                            else
                                return "No Decoder for " + this.Name + Environment.NewLine +
                                       OSDParser.SerializeLLSDNotationFormatted(data) + Environment.NewLine +
                                       "Please report this at http://jira.openmetaverse.org Be sure to include the entire message.";
                        }
                    }
                }
                else
                {
                    if (this.RequestBytes != null && this.RequestBytes.Length > 0)
                    {
                        if (this.RequestBytes[0] == 60)
                        {
                            OSD osd = OSDParser.Deserialize(this.RequestBytes);
                            if (osd is OSDMap)
                            {
                                IMessage message = null;
                                OSDMap data = (OSDMap)osd;

                                if (data.ContainsKey("body"))
                                    message = MessageUtils.DecodeEvent(this.Name, (OSDMap)data["body"]);
                                else
                                    message = MessageUtils.DecodeEvent(this.Name, data);

                                if (message != null)
                                    return PacketDecoder.MessageToString(message, 0);
                                else
                                    return "No Decoder for " + this.Name + Environment.NewLine +
                                        OSDParser.SerializeLLSDNotationFormatted(data) + Environment.NewLine +
                                        "Please report this at http://jira.openmetaverse.org Be sure to include the entire message.";
                            }
                            else
                            {
                                return osd.ToString();
                            }
                        }
                        else
                        {
                            // this means its probably a script or asset using the uploader capability
                            // so we'll just return the raw bytes as a string
                            //if (this.RequestBytes[0] == 100)
                            //{
                            return Utils.BytesToString(this.RequestBytes);
                            //}
                        }
                    }
                    else
                    {
                        return String.Empty;
                    }
                }
            }
            catch { }
            return String.Empty;
        }

        public override string ToRawString(Direction direction)
        {
            try
            {
                if (direction == Direction.Incoming)
                {
                    if (this.ResponseBytes != null)
                    {
                        StringBuilder result = new StringBuilder();
                        foreach (String key in ResponseHeaders.Keys)
                        {
                            result.AppendFormat("{0} {1}" + Environment.NewLine, key, ResponseHeaders[key]);
                        }
                        result.AppendLine();
                        result.AppendLine(OpenMetaverse.Utils.BytesToString(this.ResponseBytes));
                        return result.ToString();
                    }
                    else
                        return String.Empty;
                }
                else
                {
                    if (this.RequestBytes != null)
                    {
                        StringBuilder result = new StringBuilder();
                        result.AppendFormat("Request URI: {0}{1}", FullUri, Environment.NewLine);
                        foreach (String key in RequestHeaders.Keys)
                        {
                            result.AppendFormat("{0}: {1}" + Environment.NewLine, key, RequestHeaders[key]);
                        }
                        result.AppendLine();
                        result.AppendLine(OpenMetaverse.Utils.BytesToString(this.RequestBytes));
                        return result.ToString();
                    }
                    else
                        return String.Empty;
                }
            }
            catch { }
            return string.Empty;
        }

        public override byte[] ToBytes(Direction direction)
        {
            if (direction == Direction.Incoming)
            {
                if (this.ResponseBytes != null)
                    return this.ResponseBytes;
                else
                    return base.ToBytes(direction);
            }
            else
            {
                if (this.RequestBytes != null)
                    return this.RequestBytes;
                else
                    return base.ToBytes(direction);
            }
        }

        public override string ToStringNotation(Direction direction)
        {
            try
            {
                if (direction == Direction.Incoming)
                {
                    if (this.ResponseBytes != null)
                        return BytesToOsd(this.ResponseBytes);
                    //return this.ResponseBytes;
                    else
                        return base.ToStringNotation(direction);
                }
                else
                {
                    if (this.RequestBytes != null)
                    {
                        return BytesToOsd(this.RequestBytes);
                    }
                    else
                        return base.ToStringNotation(direction);
                }
            }
            catch { }
            return string.Empty;
        }

        public override string ToXml(Direction direction)
        {
            try
            {
                if (direction == Direction.Incoming)
                {
                    if (this.ResponseBytes != null)
                        return BytesToXml(this.ResponseBytes);
                    else
                        return base.ToXml(direction);
                }
                else
                {
                    if (this.RequestBytes != null)
                        return BytesToXml(this.RequestBytes);
                    else
                        return base.ToXml(direction);
                }
            }
            catch { }
            return string.Empty;
        }

        // Sanity check the bytes are infact OSD
        private string BytesToOsd(byte[] bytes)
        {
            try
            {
                OSD osd = OSDParser.Deserialize(bytes);
                return OSDParser.SerializeLLSDNotationFormatted(osd);
            }
            catch (LitJson.JsonException)
            {
                // unable to decode as notation format
                return base.ToStringNotation(this.Direction);
            }            
        }

        // Sanity check the bytes are infact an XML
        private string BytesToXml(byte[] bytes)
        {
            String result = Utils.BytesToString(bytes);
            if (result.StartsWith("<?xml"))
                return result;
            else
                return base.ToXml(this.Direction);
        }


        public override byte[] Serialize()
        {
            OSDMap map = new OSDMap(5);
            map["Name"] = OSD.FromString(this.Name);
            map["Host"] = OSD.FromString(this.Host);
            map["RequestBytes"] = OSD.FromBinary(this.RequestBytes);
            map["ResponseBytes"] = OSD.FromBinary(this.ResponseBytes);
            map["Direction"] = OSD.FromInteger((int)this.Direction);
            map["ContentType"] = OSD.FromString(this.ContentType);
            map["Protocol"] = OSD.FromString(this.Protocol);

            OSDArray requestHeadersArray = new OSDArray();
            foreach (String key in this.RequestHeaders.Keys)
            {
                OSDMap rMap = new OSDMap(1);
                rMap[key] = OSD.FromString(this.RequestHeaders[key]);
                requestHeadersArray.Add(rMap);
            }
            if(requestHeadersArray.Count > 0)
                map["RequestHeaders"] = requestHeadersArray;

            OSDArray responseHeadersArray = new OSDArray();
            foreach (String key in this.ResponseHeaders.Keys)
            {
                OSDMap rMap = new OSDMap(1);
                rMap[key] = OSD.FromString(this.ResponseHeaders[key]);
                responseHeadersArray.Add(rMap);
            }
            if(responseHeadersArray.Count > 0)
                map["ResponseHeaders"] = responseHeadersArray;

            return OpenMetaverse.Utils.StringToBytes(map.ToString());
        }

        public override Session Deserialize(byte[] bytes)
        {
            OSDMap map = (OSDMap)OSDParser.DeserializeLLSDNotation(OpenMetaverse.Utils.BytesToString(bytes));

            this.Name = map["Name"].AsString();
            this.Host = map["Host"].AsString();
            this.RequestBytes = map["RequestBytes"].AsBinary();
            this.ResponseBytes = map["ResponseBytes"].AsBinary();
            this.Direction = (Direction)map["Direction"].AsInteger();
            this.Length = ResponseBytes.Length + RequestBytes.Length;
            this.ContentType = map["ContentType"].AsString();
            this.Protocol = map["Protocol"].AsString();

            this.RequestHeaders = new WebHeaderCollection();
            if (map.ContainsKey("RequestHeaders"))
            {
                OSDArray requestHeadersArray = (OSDArray)map["RequestHeaders"];
                for (int i = 0; i < requestHeadersArray.Count; i++)
                {
                    OSDMap rMap = (OSDMap)requestHeadersArray[i];
                    foreach (string key in rMap.Keys)
                    {
                        this.RequestHeaders.Add(key, rMap[key].AsString());
                    }
                }
            }

            this.ResponseHeaders = new WebHeaderCollection();
            if (map.ContainsKey("ResponseHeaders"))
            {
                OSDArray responseHeadersArray = (OSDArray)map["ResponseHeaders"];
                for (int i = 0; i < responseHeadersArray.Count; i++)
                {
                    OSDMap rMap = (OSDMap)responseHeadersArray[i];
                    foreach (string key in rMap.Keys)
                    {
                        this.ResponseHeaders.Add(key, rMap[key].AsString());
                    }
                }
            }

            return this;
        }
    }
    #endregion Capabilities

    #region Login
    internal sealed class SessionLogin : Session
    {
        private object Data { get; set; }
        //request, direction, comboBoxLoginURL.Text
        public SessionLogin() : base() { this.Protocol = "https"; }
        public SessionLogin(object request, Direction direction, String url, String contentType)
            : base()
        {
            this.Data = request;
            this.Direction = direction;
            this.Host = url;
            this.ContentType = contentType;
            this.Name = (direction == Direction.Incoming) ? "Login Response" : "Login Request";
            this.Protocol = "https";
            this.Length = this.Data.ToString().Length;
        }

        public override string ToPrettyString(Direction direction)
        {
            if (direction == this.Direction)
            {
                return this.Data.ToString();
            }
            else
            {
                return String.Empty;
            }
        }

        public override string ToRawString(Direction direction)
        {
            if (direction == this.Direction)
            {
                return this.Data.ToString();
            }
            else
            {
                return String.Empty;
            }
        }
        public override string ToXml(Direction direction)
        {
            return base.ToXml(direction);

            //if (direction == this.Direction)
            //{
            //    return this.Data.ToString();
            //}
            //else
            //{
            //    return base.ToXml(direction);
            //}
        }

        public override byte[] ToBytes(Direction direction)
        {
            if (direction == this.Direction)
            {
                return OpenMetaverse.Utils.StringToBytes(this.Data.ToString());
            }
            else
            {
                return base.ToBytes(direction);
            }
        }

        public override byte[] Serialize()
        {
            OSDMap map = new OSDMap(6);
            map["Name"] = OSD.FromString(this.Name);
            map["Host"] = OSD.FromString(this.Host);
            map["Data"] = OSD.FromString(this.Data.ToString());
            map["Direction"] = OSD.FromInteger((int)this.Direction);
            map["ContentType"] = OSD.FromString(this.ContentType);
            map["Protocol"] = OSD.FromString(this.Protocol);

            return OpenMetaverse.Utils.StringToBytes(map.ToString());
        }

        public override Session Deserialize(byte[] bytes)
        {
            OSDMap map = (OSDMap)OSDParser.DeserializeLLSDNotation(OpenMetaverse.Utils.BytesToString(bytes));

            this.Name = map["Name"].AsString();
            this.Host = map["Host"].AsString();
            this.Data = map["Data"].AsString();
            this.Length = this.Data.ToString().Length;
            this.Direction = (Direction)map["Direction"].AsInteger();
            this.ContentType = map["ContentType"].AsString();
            this.Protocol = map["Protocol"].AsString();

            return this;
        }
    }
    #endregion Login

    #region EventQueue Messages
    internal class SessionEvent : Session
    {
        private byte[] ResponseBytes;
        private WebHeaderCollection ResponseHeaders;

        public SessionEvent() : base() { this.Protocol = "EventQ"; }
        public SessionEvent(byte[] responseBytes, WebHeaderCollection responseHeaders,
            String uri, String capsKey, String proto)
            : base()
        {
            this.Protocol = proto;
            this.Direction = Direction.Incoming; // EventQueue Messages are always inbound from the simulator
            this.ResponseBytes = responseBytes;
            this.ResponseHeaders = responseHeaders;
            this.Host = uri;
            this.Name = capsKey;
            this.ContentType = responseHeaders.Get("Content-Type");
            var ContentLength = responseHeaders.Get("Content-Length");
            if (ContentLength != null)
                this.Length = Int32.Parse (ContentLength);
            else
                this.Length = 0;
        }

        public override string ToPrettyString(Direction direction)
        {
            if (direction == this.Direction)
            {
                IMessage message = null;
                OSD osd = OSDParser.Deserialize(this.ResponseBytes);
                OSDMap data = (OSDMap)osd;
                if (data.ContainsKey("body"))
                    message = MessageUtils.DecodeEvent(this.Name, (OSDMap)data["body"]);
                else
                    message = MessageUtils.DecodeEvent(this.Name, data);

                if (message != null)
                    return PacketDecoder.MessageToString(message, 0);
                else
                    return "No Decoder for " + this.Name + Environment.NewLine + osd.ToString();
            }
            else
            {
                return String.Empty;
            }
        }

        public override byte[] ToBytes(Direction direction)
        {
            if (direction == this.Direction)
            {
                return this.ResponseBytes;
            }
            else
            {
                return base.ToBytes(direction);
            }
        }

        public override string ToRawString(Direction direction)
        {

            if (direction == this.Direction)
            {
                StringBuilder result = new StringBuilder();
                foreach (String key in ResponseHeaders.Keys)
                {
                    result.AppendFormat("{0} {1}" + Environment.NewLine, key, ResponseHeaders[key]);
                }
                result.AppendLine();
                result.AppendLine(this.ToXml(direction));
                return result.ToString();
            }
            else
            {
                return String.Empty;
            }
        }

        public override string ToXml(Direction direction)
        {
            if (direction == this.Direction)
            {
                return OpenMetaverse.Utils.BytesToString(this.ResponseBytes);
            }
            else
            {
                return base.ToXml(direction);
            }
        }

        public override string ToStringNotation(Direction direction)
        {
            if (direction == this.Direction)
            {
                OSD osd = OSDParser.DeserializeLLSDXml(this.ResponseBytes);
                return osd.ToString();
            }
            else
            {
                return base.ToStringNotation(direction);
            }
        }

        public override byte[] Serialize()
        {
            OSDMap map = new OSDMap(7);
            map["Name"] = OSD.FromString(this.Name);
            map["Host"] = OSD.FromString(this.Host);
            map["ResponseBytes"] = OSD.FromBinary(this.ResponseBytes);
            map["Direction"] = OSD.FromInteger((int)this.Direction);
            map["ContentType"] = OSD.FromString(this.ContentType);
            map["Protocol"] = OSD.FromString(this.Protocol);

            OSDArray responseHeadersArray = new OSDArray();
            foreach (String key in this.ResponseHeaders.Keys)
            {
                OSDMap rMap = new OSDMap(1);
                rMap[key] = OSD.FromString(this.ResponseHeaders[key]);
                responseHeadersArray.Add(rMap);
            }
            map["ResponseHeaders"] = responseHeadersArray;

            return Utils.StringToBytes(map.ToString());
        }

        public override Session Deserialize(byte[] bytes)
        {
            OSDMap map = (OSDMap)OSDParser.DeserializeLLSDNotation(OpenMetaverse.Utils.BytesToString(bytes));

            this.Name = map["Name"].AsString();
            this.Host = map["Host"].AsString();
            this.ResponseBytes = map["ResponseBytes"].AsBinary();
            this.Direction = (Direction)map["Direction"].AsInteger();
            this.ContentType = map["ContentType"].AsString();
            this.Protocol = map["Protocol"].AsString();
            this.Length = ResponseBytes.Length;

            if (map.ContainsKey("ResponseHeaders"))
            {
                this.ResponseHeaders = new WebHeaderCollection();
                OSDArray responseHeadersArray = (OSDArray)map["ResponseHeaders"];
                for (int i = 0; i < responseHeadersArray.Count; i++)
                {
                    OSDMap rMap = (OSDMap)responseHeadersArray[i];
                    foreach (string key in rMap.Keys)
                    {
                        this.ResponseHeaders.Add(key, rMap[key].AsString());
                    }
                }
            }
            return this;
        }
    }
    #endregion
}