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); }
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); }
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 }
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); }