Пример #1
0
        // char* AMF_Encode(AMFObject* obj, char* pBuffer, char* pBufEnd);
        // char* AMF_EncodeEcmaArray(AMFObject* obj, char* pBuffer, char* pBufEnd);
        // char* AMF_EncodeArray(AMFObject* obj, char* pBuffer, char* pBufEnd);

        /// <summary> int AMF_Decode(AMFObject * obj, const char *pBuffer, int nSize, int bDecodeName); </summary>
        public static int AMF_Decode(AMFObject obj, byte[] buf, int pbuf, int nSize, bool bDecodeName)
        {
            int  nOriginalSize = nSize;
            bool bError        = false; /* if there is an error while decoding - try to at least find the end mark AMF_OBJECT_END */

            obj.o_num   = 0;
            obj.o_props = null;
            while (nSize > 0)
            {
                if (nSize >= 3)
                {
                    if (AMF.AMF_DecodeInt24(buf, pbuf) == (uint)AMFDataType.AMF_OBJECT_END)
                    {
                        nSize -= 3;
                        bError = false;
                        break;
                    }
                }

                if (bError)
                {
                    Log.RTMP_Log(Log.RTMP_LogLevel.RTMP_LOGERROR, "DECODING ERROR, IGNORING BYTES UNTIL NEXT KNOWN PATTERN!");
                    nSize--;
                    pbuf++;
                    continue;
                }

                AMFObjectProperty prop = new AMFObjectProperty();
                int nRes = AMFObjectProperty.AMFProp_Decode(prop, buf, pbuf, nSize, bDecodeName);
                if (nRes == -1)
                {
                    bError = true;
                }
                else
                {
                    nSize -= nRes;
                    pbuf  += nRes;
                    AMF_AddProp(obj, prop);
                }
            }

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

            return(nOriginalSize - nSize);
        }
Пример #2
0
        /// <summary> int AMFProp_Decode(AMFObjectProperty *prop, const char *pBuffer, int nSize, int bDecodeName)</summary>
        public static int AMFProp_Decode(AMFObjectProperty prop, byte[] buf, int pBuffer, int nSize, bool bDecodeName)
        {
            const string __FUNCTION__  = "AMFProp_Decode";
            int          nOriginalSize = nSize;

            prop.p_name = new AVal();

            if (nSize == 0 || pBuffer > buf.Length)
            {
                Log.RTMP_Log(Log.RTMP_LogLevel.RTMP_LOGDEBUG, "{0}: Empty buffer/no buffer pointer!", __FUNCTION__);
                return(-1);
            }

            if (bDecodeName && nSize < 4)
            {
                /* at least name (length + at least 1 byte) and 1 byte of data */
                Log.RTMP_Log(Log.RTMP_LogLevel.RTMP_LOGDEBUG, "{0}: Not enough data for decoding with name, less than 4 bytes!", __FUNCTION__);
                return(-1);
            }

            if (bDecodeName)
            {
                var nNameSize = AMF.AMF_DecodeInt16(buf, pBuffer);
                if (nNameSize > nSize - 2)
                {
                    Log.RTMP_Log(Log.RTMP_LogLevel.RTMP_LOGDEBUG,
                                 "{0}: Name size out of range: namesize ({1}) > len ({2}) - 2",
                                 __FUNCTION__, nNameSize, nSize);
                    return(-1);
                }

                AVal name;
                AMF.AMF_DecodeString(buf, pBuffer, out name);
                prop.p_name = name;
                nSize      -= 2 + nNameSize;
                pBuffer    += 2 + nNameSize;
            }

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

            nSize--;

            prop.p_type = (AMFDataType)buf[pBuffer++]; // *pBuffer++;
            switch (prop.p_type)
            {
            case AMFDataType.AMF_NUMBER:
                if (nSize < 8)
                {
                    return(-1);
                }

                prop.p_number = AMF.AMF_DecodeNumber(buf, pBuffer);
                nSize        -= 8;
                break;

            case AMFDataType.AMF_BOOLEAN:
                if (nSize < 1)
                {
                    return(-1);
                }

                prop.p_number = AMF.AMF_DecodeBoolean(buf, pBuffer) ? 1 : 0;
                nSize--;
                break;

            case AMFDataType.AMF_STRING:
            {
                var nStringSize = AMF.AMF_DecodeInt16(buf, pBuffer);

                if (nSize < (long)nStringSize + 2)
                {
                    return(-1);
                }

                AVal v;
                AMF.AMF_DecodeString(buf, pBuffer, out v);
                prop.p_aval = v;
                nSize      -= (2 + nStringSize);
                break;
            }

            case AMFDataType.AMF_OBJECT:
            {
                int nRes = AMFObject.AMF_Decode(prop.p_object, buf, pBuffer, nSize, true);
                if (nRes == -1)
                {
                    return(-1);
                }

                nSize -= nRes;
                break;
            }

            case AMFDataType.AMF_MOVIECLIP:
                Log.RTMP_Log(Log.RTMP_LogLevel.RTMP_LOGERROR, "AMF_MOVIECLIP reserved!");
                return(-1);

            case AMFDataType.AMF_NULL:
            case AMFDataType.AMF_UNDEFINED:
            case AMFDataType.AMF_UNSUPPORTED:
                prop.p_type = AMFDataType.AMF_NULL;
                break;

            case AMFDataType.AMF_REFERENCE:
                Log.RTMP_Log(Log.RTMP_LogLevel.RTMP_LOGERROR, "AMF_REFERENCE not supported!");
                return(-1);

            case AMFDataType.AMF_ECMA_ARRAY:
            {
                nSize -= 4;

                /* next comes the rest, mixed array has a final 0x000009 mark and names, so its an object */
                var nRes = AMFObject.AMF_Decode(prop.p_object, buf, pBuffer + 4, nSize, true);
                if (nRes == -1)
                {
                    return(-1);
                }

                nSize -= nRes;
            }
            break;

            case AMFDataType.AMF_OBJECT_END:
                return(-1);

            case AMFDataType.AMF_STRICT_ARRAY:
            {
                var nArrayLen = AMF.AMF_DecodeInt32(buf, pBuffer);
                nSize -= 4;

                var nRes = AMFObject.AMF_DecodeArray(prop.p_object, buf, pBuffer + 4, nSize, (int)nArrayLen, false);
                if (nRes == -1)
                {
                    return(-1);
                }

                nSize -= nRes;
            }
            break;

            case AMFDataType.AMF_DATE:
            {
                Log.RTMP_Log(Log.RTMP_LogLevel.RTMP_LOGDEBUG, "AMF_DATE");

                if (nSize < 10)
                {
                    return(-1);
                }

                prop.p_number    = AMF.AMF_DecodeNumber(buf, pBuffer);
                prop.p_UTCoffset = (short)AMF.AMF_DecodeInt16(buf, pBuffer + 8);

                nSize -= 10;
                break;
            }

            case AMFDataType.AMF_LONG_STRING:
            case AMFDataType.AMF_XML_DOC:
            {
                var nStringSize = AMF.AMF_DecodeInt32(buf, pBuffer);
                if (nSize < (long)nStringSize + 4)
                {
                    return(-1);
                }

                AVal v;
                AMF.AMF_DecodeLongString(buf, pBuffer, out v);
                prop.p_aval = v;
                nSize      -= (int)(4 + nStringSize);
                if (prop.p_type == AMFDataType.AMF_LONG_STRING)
                {
                    prop.p_type = AMFDataType.AMF_STRING;
                }

                break;
            }

            case AMFDataType.AMF_RECORDSET:
                Log.RTMP_Log(Log.RTMP_LogLevel.RTMP_LOGERROR, "AMF_RECORDSET reserved!");
                return(-1);

            case AMFDataType.AMF_TYPED_OBJECT:
                Log.RTMP_Log(Log.RTMP_LogLevel.RTMP_LOGERROR, "AMF_TYPED_OBJECT not supported!");
                return(-1);

            case AMFDataType.AMF_AVMPLUS:
            {
                var nRes = AMFObject.AMF3_Decode(prop.p_object, buf, pBuffer, nSize, true);
                if (nRes == -1)
                {
                    return(-1);
                }
                nSize      -= nRes;
                prop.p_type = AMFDataType.AMF_OBJECT;
                break;
            }

            default:
                Log.RTMP_Log(Log.RTMP_LogLevel.RTMP_LOGDEBUG, "{0} - unknown datatype 0x{1:x2}, @{2}", __FUNCTION__, prop.p_type, pBuffer - 1);
                return(-1);
            }

            return(nOriginalSize - nSize);
        }