Example #1
0
 public void Encode(List <byte> output)
 {
     output.Add((byte)AMFDataType.AMF_OBJECT);
     foreach (AMFObjectProperty aProp in properties)
     {
         aProp.Encode(output);
     } //foreach
     RTMPHelper.EncodeInt24(output, (int)AMFDataType.AMF_OBJECT_END);
 }
Example #2
0
        public int Decode(byte[] pBuffer, int bufferOffset, int size, bool bDecodeName)
        {
            int  originalSize = size;
            bool error        = false; // if there is an error while decoding - try to at least find the end mark 0x000009

            while (size >= 3)
            {
                if (RTMPHelper.ReadInt24(pBuffer, bufferOffset) == 0x00000009)
                {
                    size -= 3;
                    error = false;
                    break;
                }

                if (error)
                {
                    size--;
                    bufferOffset++;
                    continue;
                }

                AMFObjectProperty prop = new AMFObjectProperty();
                int result             = prop.Decode(pBuffer, bufferOffset, size, bDecodeName);
                if (result == -1)
                {
                    error = true;
                }
                else
                {
                    size         -= result;
                    bufferOffset += result;
                    properties.Add(prop);
                }
            }

            if (error)
            {
                return(-1);
            }

            return(originalSize - size);
        }
Example #3
0
        public void Encode(List <byte> output)
        {
            if (type == AMFDataType.AMF_INVALID)
            {
                return;
            }

            switch (type)
            {
            case AMFDataType.AMF_NUMBER:
                if (string.IsNullOrEmpty(stringName))
                {
                    RTMPHelper.EncodeNumber(output, NumberValue);
                }
                else
                {
                    RTMPHelper.EncodeNumber(output, stringName, NumberValue);
                }
                break;

            case AMFDataType.AMF_BOOLEAN:
                if (string.IsNullOrEmpty(stringName))
                {
                    RTMPHelper.EncodeBoolean(output, BooleanValue);
                }
                else
                {
                    RTMPHelper.EncodeBoolean(output, stringName, BooleanValue);
                }
                break;

            case AMFDataType.AMF_STRING:
                if (string.IsNullOrEmpty(stringName))
                {
                    RTMPHelper.EncodeString(output, StringValue);
                }
                else
                {
                    RTMPHelper.EncodeString(output, stringName, StringValue);
                }
                break;

            case AMFDataType.AMF_NULL:
                output.Add(0x05);
                break;

            case AMFDataType.AMF_OBJECT:
                if (!string.IsNullOrEmpty(stringName))
                {
                    short length = System.Net.IPAddress.HostToNetworkOrder((short)stringName.Length);
                    output.AddRange(BitConverter.GetBytes(length));
                    output.AddRange(Encoding.ASCII.GetBytes(stringName));
                }
                objVal.Encode(output);
                break;

            default:
                LibRTMPLogger.Log(LibRTMPLogLevel.Trace, string.Format("AMFObjectProperty.Encode invalid type: {0}", type));
                break;
            } //switch
        }
Example #4
0
        public int Decode(byte[] buffer, int bufferOffset, int size, bool bDecodeName)
        {
            int originalSize = size;

            if (size == 0 || buffer == null)
            {
                return(-1);
            }

            if (buffer[bufferOffset] == 0x05)
            {
                type = AMFDataType.AMF_NULL;
                return(1);
            }

            if (bDecodeName && size < 4) // at least name (length + at least 1 byte) and 1 byte of data
            {
                return(-1);
            }

            if (bDecodeName)
            {
                ushort nNameSize = RTMPHelper.ReadInt16(buffer, bufferOffset);
                if (nNameSize > size - (short)sizeof(short))
                {
                    return(-1);
                }

                stringName    = RTMPHelper.ReadString(buffer, bufferOffset);
                size         -= sizeof(short) + stringName.Length;
                bufferOffset += sizeof(short) + stringName.Length;
            }

            if (size == 0)
            {
                return(-1);
            }

            size--;

            int stringSize = 0;
            int result     = 0;

            switch (buffer[bufferOffset])
            {
            case (byte)AMFDataType.AMF_NUMBER:
                if (size < (int)sizeof(double))
                {
                    return(-1);
                }
                numVal = RTMPHelper.ReadNumber(buffer, bufferOffset + 1);
                size  -= sizeof(double);
                type   = AMFDataType.AMF_NUMBER;
                break;

            case (byte)AMFDataType.AMF_BOOLEAN:
                if (size < 1)
                {
                    return(-1);
                }
                numVal = Convert.ToDouble(RTMPHelper.ReadBool(buffer, bufferOffset + 1));
                size--;
                type = AMFDataType.AMF_BOOLEAN;
                break;

            case (byte)AMFDataType.AMF_STRING:
                stringSize = RTMPHelper.ReadInt16(buffer, bufferOffset + 1);
                if (size < stringSize + (int)sizeof(short))
                {
                    return(-1);
                }
                stringVal = RTMPHelper.ReadString(buffer, bufferOffset + 1);
                size     -= sizeof(short) + stringSize;
                type      = AMFDataType.AMF_STRING;
                break;

            case (byte)AMFDataType.AMF_OBJECT:
                objVal = new AMFObject();
                result = objVal.Decode(buffer, bufferOffset + 1, size, true);
                if (result == -1)
                {
                    return(-1);
                }
                size -= result;
                type  = AMFDataType.AMF_OBJECT;
                break;

            case (byte)AMFDataType.AMF_MOVIECLIP:
                LibRTMPLogger.Log(LibRTMPLogLevel.Trace, "AMF_MOVIECLIP reserved!");
                return(-1);

            case (byte)AMFDataType.AMF_NULL:
            case (byte)AMFDataType.AMF_UNDEFINED:
            case (byte)AMFDataType.AMF_UNSUPPORTED:
                type = AMFDataType.AMF_NULL;
                break;

            case (byte)AMFDataType.AMF_REFERENCE:
                LibRTMPLogger.Log(LibRTMPLogLevel.Trace, "AMF_REFERENCE not supported!");
                return(-1);

            case (byte)AMFDataType.AMF_ECMA_ARRAY:
                size -= 4;

                // next comes the rest, mixed array has a final 0x000009 mark and names, so its an object
                objVal = new AMFObject();
                result = objVal.Decode(buffer, bufferOffset + 5, size, true);
                if (result == -1)
                {
                    return(-1);
                }
                size -= result;
                type  = AMFDataType.AMF_OBJECT;
                break;

            case (byte)AMFDataType.AMF_OBJECT_END:
                return(-1);

            case (byte)AMFDataType.AMF_STRICT_ARRAY:
                int nArrayLen = RTMPHelper.ReadInt32(buffer, bufferOffset + 1);
                size -= 4;

                objVal = new AMFObject();
                result = objVal.DecodeArray(buffer, bufferOffset + 5, size, nArrayLen, false);
                if (result == -1)
                {
                    return(-1);
                }
                size -= result;
                type  = AMFDataType.AMF_OBJECT;
                break;

            case (byte)AMFDataType.AMF_DATE:
                if (size < 10)
                {
                    return(-1);
                }
                date          = RTMPHelper.ReadNumber(buffer, bufferOffset + 1);
                dateUTCOffset = RTMPHelper.ReadInt16(buffer, bufferOffset + 9);
                size         -= 10;
                break;

            case (byte)AMFDataType.AMF_LONG_STRING:
                stringSize = RTMPHelper.ReadInt32(buffer, bufferOffset + 1);
                if (size < stringSize + 4)
                {
                    return(-1);
                }
                stringVal = RTMPHelper.ReadLongString(buffer, bufferOffset + 1);
                size     -= (4 + stringSize);
                type      = AMFDataType.AMF_STRING;
                break;

            case (byte)AMFDataType.AMF_RECORDSET:
                LibRTMPLogger.Log(LibRTMPLogLevel.Trace, "AMFObjectProperty.Decode AMF_RECORDSET reserved!");
                return(-1);

            case (byte)AMFDataType.AMF_XML_DOC:
                LibRTMPLogger.Log(LibRTMPLogLevel.Trace, "AMFObjectProperty.Decode AMF_XML_DOC not supported!");
                return(-1);

            case (byte)AMFDataType.AMF_TYPED_OBJECT:
                LibRTMPLogger.Log(LibRTMPLogLevel.Trace, "AMFObjectProperty.Decode AMF_TYPED_OBJECT not supported!");
                return(-1);

            default:
                LibRTMPLogger.Log(LibRTMPLogLevel.Trace, string.Format("AMFObjectProperty.Decode Unknown datatype {0}", buffer[bufferOffset]));
                return(-1);
            } //switch

            return(originalSize - size);
        }