private static void DecodeSharedObject(SharedObjectMessage so, ByteBuffer stream, RtmpReader reader)
        {
            while (stream.HasRemaining)
            {
                SharedObjectEventType type = SharedObjectTypeMapping.ToType(reader.ReadByte());
                string key  = null;
                object obj2 = null;
                int    @int = stream.GetInt();
                switch (type)
                {
                case SharedObjectEventType.CLIENT_STATUS:
                    key  = reader.ReadString();
                    obj2 = reader.ReadString();
                    break;

                case SharedObjectEventType.CLIENT_UPDATE_DATA:
                    key  = reader.ReadString();
                    obj2 = reader.ReadData();
                    break;

                default:
                    if ((type != SharedObjectEventType.SERVER_SEND_MESSAGE) && (type != SharedObjectEventType.CLIENT_SEND_MESSAGE))
                    {
                        if (@int > 0)
                        {
                            key = reader.ReadString();
                            if (@int > (key.Length + 2))
                            {
                                obj2 = reader.ReadData();
                            }
                        }
                    }
                    else
                    {
                        int position = (int)stream.Position;
                        key = reader.ReadData() as string;
                        List <object> list = new List <object>();
                        while ((stream.Position - position) < @int)
                        {
                            object item = reader.ReadData();
                            list.Add(item);
                        }
                        obj2 = list;
                    }
                    break;
                }
                so.AddEvent(type, key, obj2);
            }
        }
        private static ISharedObjectMessage DecodeSharedObject(ByteBuffer stream)
        {
            RtmpReader reader     = new RtmpReader(stream);
            string     name       = reader.ReadString();
            int        version    = reader.ReadInt32();
            bool       persistent = reader.ReadInt32() == 2;

            reader.ReadInt32();
            SharedObjectMessage so = new SharedObjectMessage(null, name, version, persistent);

            DecodeSharedObject(so, stream, reader);
            return(so);
        }
        static ISharedObjectMessage DecodeSharedObject(ByteBuffer stream)
        {
            RtmpReader reader = new RtmpReader(stream);
            string     name   = reader.ReadString();
            // Read version of SO to modify
            int version = reader.ReadInt32();
            // Read persistence informations
            bool persistent = reader.ReadInt32() == 2;

            // Skip unknown bytes
            //skip(4);
            reader.ReadInt32();

            SharedObjectMessage so = new SharedObjectMessage(null, name, version, persistent);

            DecodeSharedObject(so, stream, reader);
            return(so);
        }
        static void DecodeSharedObject(SharedObjectMessage so, ByteBuffer stream, RtmpReader reader)
        {
            // Parse request body
            while (stream.HasRemaining)
            {
                byte typeCode = reader.ReadByte();
                SharedObjectEventType type = SharedObjectTypeMapping.ToType(typeCode);
                string key   = null;
                object value = null;

                int length = stream.GetInt();                //reader.ReadInt32();
                switch (type)
                {
                case SharedObjectEventType.CLIENT_STATUS:
                    // Status code
                    key = reader.ReadString();
                    // Status level
                    value = reader.ReadString();
                    break;

                case SharedObjectEventType.CLIENT_UPDATE_DATA:
                {
                    key   = reader.ReadString();
                    value = reader.ReadData();

                    /*
                     *                      key = null;
                     *                      // Map containing new attribute values
                     *                      Hashtable map = new Hashtable();
                     *                      int start = (int)stream.Position;
                     *                      while((int)stream.Position - start < length)
                     *                      {
                     *                              string tmp = reader.ReadString();
                     *                              map[tmp] = reader.ReadData();
                     *                      }
                     *                      value = map;
                     */
                }
                break;

                default:
                    if (type != SharedObjectEventType.SERVER_SEND_MESSAGE && type != SharedObjectEventType.CLIENT_SEND_MESSAGE)
                    {
                        if (length > 0)
                        {
                            key = reader.ReadString();
                            if (length > key.Length + 2)
                            {
                                value = reader.ReadData();
                            }
                        }
                    }
                    else
                    {
                        int start = (int)stream.Position;
                        // the "send" event seems to encode the handler name
                        // as complete AMF string including the string type byte
                        key = reader.ReadData() as string;
                        // read parameters
#if !(NET_1_1)
                        List <object> paramList = new List <object>();
#else
                        ArrayList paramList = new ArrayList();
#endif
                        while (stream.Position - start < length)
                        {
                            object tmp = reader.ReadData();
                            paramList.Add(tmp);
                        }
                        value = paramList;
                    }
                    break;
                }
                so.AddEvent(type, key, value);
            }
        }
		static ISharedObjectMessage DecodeFlexSharedObject(ByteBuffer stream)
		{
			// Unknown byte, always 0?
			stream.Skip(1);
			RtmpReader reader = new RtmpReader(stream);
			string name = reader.ReadString();
			// Read version of SO to modify
			int version = reader.ReadInt32();
			// Read persistence informations
			bool persistent = reader.ReadInt32() == 2;
			// Skip unknown bytes
			reader.ReadInt32();

			SharedObjectMessage so = new FlexSharedObjectMessage(null, name, version, persistent);
			DecodeSharedObject(so, stream, reader);
			return so;
		}
		static void DecodeSharedObject(SharedObjectMessage so, ByteBuffer stream, RtmpReader reader)
		{
			// Parse request body
			while(stream.HasRemaining)
			{
				byte typeCode = reader.ReadByte();
				SharedObjectEventType type = SharedObjectTypeMapping.ToType(typeCode);
				string key = null;
				object value = null;

				int length = stream.GetInt();//reader.ReadInt32();
				switch(type)
				{
					case SharedObjectEventType.CLIENT_STATUS:
						// Status code
						key = reader.ReadString();
						// Status level
						value = reader.ReadString();
						break;
					case SharedObjectEventType.CLIENT_UPDATE_DATA:
					{
                        key = reader.ReadString();
                        value = reader.ReadData();
                        /*
						key = null;
						// Map containing new attribute values
						Hashtable map = new Hashtable();
						int start = (int)stream.Position;
						while((int)stream.Position - start < length) 
						{
							string tmp = reader.ReadString();
							map[tmp] = reader.ReadData();
						}
						value = map;
                        */
					}
						break;
					default:
						if (type != SharedObjectEventType.SERVER_SEND_MESSAGE && type != SharedObjectEventType.CLIENT_SEND_MESSAGE) 
						{
							if (length > 0) 
							{
								key = reader.ReadString();
								if(length > key.Length + 2) 
								{
									value = reader.ReadData();
								}
							}
						} 
						else 
						{
							int start = (int)stream.Position;
							// the "send" event seems to encode the handler name
							// as complete AMF string including the string type byte
							key = reader.ReadData() as string;
							// read parameters
#if !(NET_1_1)
                            List<object> paramList = new List<object>();
#else
							ArrayList paramList = new ArrayList();
#endif
                            while (stream.Position - start < length)
							{
								object tmp = reader.ReadData();
								paramList.Add(tmp);
							}
							value = paramList;
						}
						break;
				}
				so.AddEvent(type, key, value);
			}
		}