OpenRTMFP/Cumulus Primer(18)AMF解析之AMFReader(續2)
OpenRTMFP/Cumulus Primer(18)AMF解析之AMFReader(續2)
- Author: 柳大·Poechant(鍾超)
- Email: zhongchao.ustc#gmail.com (#->@)
- Blog:Blog.CSDN.net/Poechant
- Date: April 24th, 2012
1 開始引用與結束引用
如下這兩個函式會在 FlowConnection 中呼叫。
inline void AMFReader::startReferencing() {
_referencing = true;
}
inline void AMFReader::stopReferencing() {
_referencing = false;
}
2 解析 AS3 ByteArray
先回顧一下 AMF3 中的ByteArray 的資料格式:
注意到,首先要讀取一個變長無符號 32 位整數,但是最低位是 1,只有 28 位用於表示資料長度。解釋完這裡,下面的解析過程才好理解。
BinaryReader& AMFReader::readByteArray(UInt32& size) {
慣例:
reset();
AMF::Type type = followingType();
Null 就返回 BinaryReaderNull。
if (type == AMF::Null) {
reader.next(1);
return BinaryReader::BinaryReaderNull;
}
如果不是 ByteArray,也返回 BinaryReaderNull:
if (type != AMF::ByteArray) {
ERROR("Type %.2x is not a AMF ByteArray type",type);
return BinaryReader::BinaryReaderNull;
}
跳過這個位元組:
reader.next(1);
注意 position 返回的是相對位置,與 AS3 中一樣。reference 表示這個地址(簡單說,引用就是地址嘛)。
UInt32 reference = reader.position();
讀取一個變長 32 位無符號整數:
size = reader.read7BitValue();
最低位是 1 的話,isInline 是 true,否則為 false。
bool isInline = size & 0x01;
右移一位,因為那一位是標誌位,上面解釋過了。
size >>= 1;
如果 isInline 是 true,表示是 ByteArray:
if (isInline) {
如果 _referencing 為 true 的話(這是一個 vector),push back this reference:
if (_referencing)
_references.push_back(reference);
}
不符合 ByteArray 的格式定義的話:
else {
if (size > _references.size()) {
ERROR("AMF3 reference not found")
return BinaryReader::BinaryReaderNull;
}
_reset = reader.position();
移動到這個 reference 的位置,_references[size] 就是這個位置(相對)。
reader.reset(_references[size]); // TODO size 作為索引,還沒有完全理解
讀取這個 reference 的 size 值給 size物件(注意 size 是這個函式傳入的引用引數,其值可以被修改)。
size = reader.read7BitValue() >> 1;
}
把讀取完 ByteArraty 的 PacketReader 返回:
return reader;
}
最後強調一點,ByteArray 的資料段最大長度為 228-1 位元組,約為 256 MB。
2 解析 AS3 Date
先看下 Date 的資料格式:
下面開始分析:
Timestamp AMFReader::readDate() {
慣例:
reset();
AMF::Type type = followingType();
Null 的話,就返回當前時間:
if (type == AMF::Null) {
reader.next(1);
return Timestamp(0);
}
如果不是 Date 型別,也返回當前時間:
if (type != AMF::Date) {
ERROR("Type %.2x is not a AMF Date type",type);
return Timestamp(0);
}
reader.next(1);
double result = 0;
如果是 AMF3:
if(_amf3) {
先讀取 flag,最低一位必須是 1,其他位丟到垃圾桶。
UInt32 flags = reader.read7BitValue();
當前相對位置。
UInt32 reference = reader.position();
是 1 就 push back 到 _references 裡。
bool isInline = flags & 0x01;
if (isInline) {
if(_referencing)
_references.push_back(reference);
讀取一個 double,到 result 裡(result 也是 double 型別哦~)。
reader >> result;
}
如果標誌位不是 1,麻煩不少噠。。。
else {
flags >>= 1;
如果 flag 超了,就返回當前時間作為時間戳作為 Date。
if (flags > _references.size()) {
ERROR("AMF3 reference not found")
return Timestamp(0);
}
這段與 ByteArray 那段一樣:
_reset = reader.position();
reader.reset(_references[flags]);
reader >> result;
reset();
}
返回嘍~
return Timestamp((Timestamp::TimeVal) result * 1000);
}
reader >> result;
讀倆,因為是 double(64 位):
reader.next(2); // Timezone, useless
返回嘍~
return Timestamp((Timestamp::TimeVal) result * 1000);
}
3 解析 AS3 Dictionary
bool AMFReader::readDictionary(bool& weakKeys) {
下面這段我們就略了。。
reset();
AMF::Type type = followingType();
if (type == AMF::Null) {
reader.next(1);
return false;
}
if (type != AMF::Dictionary) {
ERROR("Type %.2x is not a AMF Dictionary type",type);
return false;
}
跳過 type:
// AMF3
reader.next(1); // marker
當前相對位置值作為 reference,再讀個 size,還是最低位必須為 1,不是就返回 false。
UInt32 reference = reader.position();
UInt32 size = reader.read7BitValue();
bool isInline = size & 0x01;
size >>= 1;
if(!isInline && size>_references.size()) {
ERROR("AMF3 reference not found")
return false;
}
下面要呼叫到 ObjectRef 建構函式,這裡再把其實現拿出來看看,其實主要是初始化了哪些成員。
ObjectDef(UInt32 amf3,UInt8 arrayType=0)
: amf3(amf3),
reset(0),
dynamic(false),
externalizable(false),
count(0),
arrayType(arrayType) {
}
可以看到要有一個 amf3,還有 reset 置為 0,dynamic 置為 false,externalizable 也是 false,count 是 0,arrayType 成員要賦值。
上面是插播哦,下面還要繼續噠。建立這麼一個物件,注意是 new 出來的,所以我們在《OpenRTMFP/Cumulus Primer(16)AMF解析之AMFReader》一文中提到了 AMFReader 的解構函式中要對 _objectRef 的每個元素逐一析構的。arrayType 就設定為 AMF3_DICTIONARY。
ObjectDef* pObjectDef = new ObjectDef(_amf3, AMF3_DICTIONARY);
pObjectDef->dynamic=true;
_objectDefs.push_back(pObjectDef);
如果標誌位是 1,就直接 push back,跟之前一樣。不過這裡多了一個 pObjectDef,所以還要設定一下它的計數為 size,就是 dictionary 資料大小。
if (isInline) {
if (_referencing)
_references.push_back(reference);
pObjectDef->count = size;
}
如果標誌位是 0,就把 count 設定為下一個變長整數值。
else {
pObjectDef->reset = reader.position();
reader.reset(_references[size]);
pObjectDef->count = reader.read7BitValue() >> 1;
}
pObjectDef->count *= 2;
讀一個位元組,如果最小位是 1,weakKeys 就是 true,否則為 false。
weakKeys = reader.read8() & 0x01;
return true;
}
-
轉載請註明來自柳大的CSDN部落格:Blog.CSDN.net/Poechant
-
相關文章
- OpenRTMFP/Cumulus Primer(17)AMF解析之AMFReader(續1)
- OpenRTMFP/Cumulus Primer(16)AMF解析之AMFReader
- OpenRTMFP/Cumulus Primer(14)AMF解析之PacketReader/Writer
- OpenRTMFP/Cumulus Primer(9)AMF解析之BinaryReader/Writer
- OpenRTMFP/Cumulus Primer(15)AMF解析之資料型別定義資料型別
- OpenRTMFP/Cumulus Primer(9)AMF 處理方式解析——BinaryReader/Writer
- OpenRTMFP/Cumulus Primer(6)CumulusServer啟動流程分析(續2)Server
- OpenRTMFP/Cumulus Primer(5)CumulusServer啟動流程分析(續)Server
- OpenRTMFP/Cumulus Primer(7)CumulusServer啟動流程分析(續3)Server
- OpenRTMFP/Cumulus Primer(5)CumulusServer啟動流程分析(續1)Server
- OpenRTMFP/Cumulus Primer(7)CumulusServer 啟動流程分析(續3)Server
- OpenRTMFP/Cumulus Primer(4)CumulusServer啟動流程分析Server
- OpenRTMFP/Cumulus Primer(13)IO管理之區域性記憶體片記憶體
- OpenRTMFP/Cumulus Primer(8)CumulusServer主程式主迴圈分析Server
- OpenRTMFP/Cumulus Primer(1)入門介紹與部署CumulusServerServer
- OpenRTMFP/Cumulus Primer(2)用Lua編寫HelloWorld應用擴充套件CumulusServer套件Server
- OpenRTMFP/Cumulus Primer(19)獨立使用CumulusLib時的執行緒安全Bug執行緒
- OpenRTMFP/Cumulus Primer(21)經由伺服器的釋出/訂閱流程的關鍵點伺服器
- OpenRTMFP/Cumulus Primer(23)執行緒邏輯分析之二:RTMFPManager對RTMFPServer的影響執行緒Server
- OpenRTMFP/Cumulus Primer(22)執行緒邏輯分析之一:RTMFPServer執行緒的啟動和等待執行緒Server
- AMF解析遇上XXE,BurpSuite也躺槍UI
- C++ Primer 課後習題解析C++
- c++ primer 之stringC++
- Oracle redo解析之-2、BBED & DUMP工具使用Oracle Redo
- Objective-C Primer(2)Private Methods and Class PropertiesObject
- 2_深入解析Oracle ASSM結構之Level 2 Bitmap BlockOracleSSMBloC
- c++_primer之第四章C++
- C_Primer第2章 C語言概述C語言
- C++ Primer Plus第6版18個重點筆記C++筆記
- 新手入門AMF協議基礎全解協議
- App Annie:2018年2月全球App市場解析APP
- [20180427]SCAN_IP DNS 反向解析2.txtDNS
- 10.18 Linux命令(續)Linux
- 我的隨行筆記2 C++ Primer Plus筆記C++
- OCFS安裝續2
- [原始碼解析] TensorFlow 分散式之 ParameterServerStrategy V2原始碼分散式Server
- Oracle 監聽器日誌解析(續)Oracle
- A Hadoop PrimerHadoop