摘要
Action Message Format (AMF)
是一种简洁的二进制格式,通常用于序列化ActionScript
object graphs(对象图?不会翻译)。一旦序列化,AMF
编码的对象图可用于会话之间持久化以及检索应用程序的公共状态,或者允许两个端通过强类型数据的交换进行通信。
AMF 0 Data Types
下方是AMF0
的16种类型的marker
。marker
位占用一个字节长度,用于描述AMF
中某种数据类型。
marker | value | remark | |
---|---|---|---|
number-marker | 0x00 | ||
boolean-marker | 0x01 | ||
string-marker | 0x02 | ||
object-marker | 0x03 | ||
movieclip-marker | 0x04 | reserved, not supported | |
null-marker | 0x05 | ||
undefined-marker | 0x06 | ||
reference-marker | 0x07 | ||
ecma-array-marker | 0x08 | ||
object-end-marker | 0x09 | ||
strict-array-marker | 0x0A | ||
date-marker | 0x0B | ||
long-string-marker | 0x0C | ||
unsupported-marker | 0x0D | ||
recordset-marker | 0x0E | reserved, not supported | |
xml-document-marker | 0x0F | ||
typed-object-marker | 0x10 |
抓包分析
因为AMF0
采用的是 big endian (network) byte order
,所以先简单看看什么是big endian
。
int val = 0x1234;
big endian:
低地址 0------->1------->2 高地址
+--------+--------+
| 0x12 | 0x34 |
+--------+--------+
little endian:
+--------+--------+
| 0x34 | 0x12 |
+--------+--------+
- Number
number-type = number-marker DOUBLE
Number
的marker
为0x00
,紫框是Number
的数值,为40 08 00 00 00 00 00 00
,我的电脑是little endian
的所以我在内存里面看到的相应的数值是00 00 00 00 00 00 08 40
。我们可以看一下rtmpdump的实现
char *AMF_EncodeNumber(char *output, char *outend, double dVal)
{
unsigned char *ci, *co;
ci = (unsigned char *)&dVal;
co = (unsigned char *)output;
co[0] = ci[7];
co[1] = ci[6];
co[2] = ci[5];
co[3] = ci[4];
co[4] = ci[3];
co[5] = ci[2];
co[6] = ci[1];
co[7] = ci[0];
}
- Boolean
boolean-type = boolean-marker U8 ; 0 is false, <> 0 is true
Boolean
的marker
为0x01
,紫框是Boolean
的数值,为0x01
,理论上只要非零就是true
rtmpdump的实现
char * AMF_EncodeBoolean(char *output, char *outend, int bVal)
{
*output++ = AMF_BOOLEAN;
*output++ = bVal ? 0x01 : 0x00;
return output;
}
- String
string-type = string-marker UTF-8
String
的marker
为0x02
,绿框是字符串的长度,值为0x0008
,紫框是String
的值,为onStatus
的ASCII
码。rtmpdump的实现
char *AMF_EncodeString(char *output, char *outend, const AVal *bv)
{
*output++ = AMF_STRING;
output = AMF_EncodeInt16(output, outend, bv->av_len);
memcpy(output, bv->av_val, bv->av_len);
output += bv->av_len;
return output;
}
- Object
object-property = (UTF-8 value-type) | (UTF-8-empty object-end-marker)
anonymous-object-type = object-marker *(object-property)
Object
类型除了可以包含其他类型之外,也可以包含Object
类型。
Object
是以Object-End
结束的,值为0x000009
。
Thanks
- rtmpdump,简直是入门引路者
最终目标是实现RTMP协议。还好前方有大量牛人实现过,感觉造轮子的时候,可以抄一下=。=
简单地实现了一下,代码地址->amf0