概述:
本方法定義了一種數據結構,可用於描述任意的樹形二進制協議,並配合一個特定的處理算法,可實現一種通用的,由該種樹形二進制協議定義的比特流解析與填充的處理,該數據結構的定義如下:
/* 以下結構用於定義一個協議節點的描述信息。 */
struct _proto_info;
typedef struct _proto_des {
const char * name; /* 用於描述一個協議節點的名稱。 */
size_t staticSize; /* 用於描述一個協議節點的大小,單位是比特,對於可變長編碼(如UTF8)的協議節點,或長度不固定的複合型(即由子協議組成的)協議節點,該值爲0。 */
uint32_t isCondition; /* 用於描述該協議節點是否爲另一個或多個協議節點的條件節點(如定義長度或標記位的協議節點),如果是,則該值爲相關協議節點的個數,因此該值的類型爲整型而非布爾型。 */
const struct _proto_des * condition; /* 用於描述該協議節點是否與一個條件節點相關,如果是,則該指針指向其條件節點的描述。 */
list_obj subDesList; /* 用於記錄該協議節點的所有下級子協議節點,該值的類型可以是任意集合類型,本實現採用的是list。 */
size_t (*SizeInBit) (const struct _proto_info * protoInfo); /* 一個可適配的,計算該協議節點大小的函數,單位爲比特, 用於計算可變長編碼或長度不固定的複合型(即該協議節點的 staticSize 爲 0 的)協議節點的大小,當該協議節點的 staticSize 不爲 0 時則返回 staticSize 的值。 */
size_t (*Length) (const struct _proto_info * protoInfo); /* 一個可適配的,計算該協議節點長度(即個數)的函數,當該函數返回值爲 0 時,即表示該協議節點不存在(此時,該協議節點必然與一個條件節點相關,且它的條件節點的值不滿足該協議節點的存在條件)。 */
size_t (*TotalSize) (const struct _proto_info * protoInfo); /* 一個可適配的,計算該協議節點總大小的函數,單位爲比特,若該協議節點的 staticSize 不爲 0,則簡單返回該協議節點的 staticSize 乘以該協議節點的 Length 函數的返回值,否則,逐個的累加該協議節點的 SizeInBit 函數的返回值,累加的次數由該協議節點的 Length 函數的返回值指定。 */
} proto_des;
/* 以下結構用於定義某段比特流的具體含義。 */
typedef struct _proto_info {
const proto_des * protoDes; /* 該段比特流對應的協議描述。 */
uint8_t * buffer; /* 該段比特流對應的緩衝區起始地址。 */
offset_t itemNum; /* 該段比特流對應的協議描述的下標(即,當對應 protoDes 的 Length 函數返回值大於0時,該值指示了這段比特流的編號),從 0 開始。 */
offset_t dataOffset; /* 該段比特流的數據偏移位,單位爲比特。 */
offset_t condOffset; /* 該段比特流的條件段(即,當對應 protoDes 的 condition 不爲 0 時,該 condition 對應的比特段)的偏移位,單位爲比特。 */
node_t subDesNode; /* 用於協議描述樹的編歷,禁止直接訪問。 */
offset_t subItemNum; /* 用於協議描述樹的編歷,禁止直接訪問。 */
} proto_info;
處理比特流的算法:
1)使用 proto_des 定義目標二進制協議的協議描述樹;
2)定義以下的數據結構用於回溯條件段:
typedef struct {
const proto_des * protoDes; /* 該條件段對應的協議描述,該協議描述的 isCondition 的值必然大於 0。*/
offset_t dataOffset; /* 該條件段的數據偏移位。 */
size_t refCount; /* 該條件段的引用計數。 */
} cond_proto_info;
3)定義以下的數據結構用於記錄處理過程中的上下文:
typedef struct {
uint8_t * dataBuf; /* 待處理比特流的緩衝區地址。 */
size_t dataSize; /* 待處理比特流的緩衝區大小。 */
offset_t dataOffset; /* 當前待處理數據的偏移位,初始值爲 0。 */
list_obj condBacktrace; /* 條件段的集合,該集合中的每一個元素都爲步驟2定義的數據結構,本實現採用的集合類型爲 list。 */
list_obj protoInfoStack; /* 緩存 proto_info 的棧,本實現採用的棧類型爲 list。 */
} protocol_parser_ctx;
4)定義以下的函數用於從一個 proto_info 的實例中創建一個步驟2)定義的 cond_proto_info 的實例,並壓入步驟3)定義的上下文中的 condBacktrace:
static void condition_backtrace_set(
list_obj * backtrace, const proto_info * protoInfo)
{
cond_proto_info_obj condObj = {0};
if ( operator_new(&cond_proto_info_des, &condObj) ) {
cond_proto_info * condInfo = (cond_proto_info *) condObj._ctx;
condInfo->protoDes = protoInfo->protoDes;
condInfo->dataOffset = protoInfo->dataOffset;
condInfo->refCount = 0;
backtrace->_cls->PushFront(backtrace->_ctx, &condObj);
}
}
5)定義以下的函數用於從步驟3)定義的上下文中的 condBacktrace 中查找條件段的偏移位,並且刪除無用的元素:
static offset_t condition_backtrace_get(
list_obj * backtrace, const proto_des * protoDes, bool ref)
{
if ( backtrace->_cls->GetItemCount(backtrace->_ctx) ) {
node_t condNode = backtrace->_cls->GetItem(backtrace->_ctx, 0);
cond_proto_info * condInfo = 0;
cond_proto_info_obj condObj = {0};
do {
backtrace->_cls->GetItemValue(condNode, &condObj);
condInfo = (cond_proto_info *) condObj._ctx;
if (condInfo->protoDes == protoDes) {
offset_t condOffset = condInfo->dataOffset;
if (ref) {
if ( protoDes->isCondition == ++(condInfo->refCount) ) {
backtrace->_cls->SwapAndDropItem(
backtrace->_ctx, condNode
);
}
}
return condOffset;
}
condNode = backtrace->_cls->GetItem(backtrace->_ctx, condNode);
} while (condNode);
}
return 0;
}
6)定義以下的函數用於初始化一個 proto_info 的實例:
static const proto_des * protocol_parser_set_proto_info(
protocol_parser_ctx * ctx,
proto_info * protoInfo,
proto_des_obj * protoDesObj,
offset_t itemNum,
bool refCond)
{
proto_des * protoDes = (proto_des *) protoDesObj->_ctx;
protoInfo->protoDes = protoDes;
protoInfo->buffer = ctx->dataBuf;
protoInfo->itemNum = itemNum;
protoInfo->dataOffset = ctx->dataOffset;
if (protoDes->condition) {
protoInfo->condOffset = condition_backtrace_get(
&ctx->condBacktrace, protoDes->condition, refCond
);
}
else
protoInfo->condOffset = 0;
return protoDes;
}
7)定義以下的函數用於創建 proto_info 的實例,並壓入步驟3)定義的上下文中的 protoInfoStack (若過程中的 proto_info 實例的協議節點是一個條件協議節點,則會執行步驟4)定義的函數):
static void protocol_parser_push_proto_des(
protocol_parser_ctx * ctx, proto_des_obj * protoDesObj, offset_t itemNum)
{
proto_des_obj desObj = *protoDesObj;
proto_info_obj protoObj = {0};
proto_info * protoInfo = 0;
const proto_des * protoDes = 0;
do {
if ( !operator_new(&proto_info_des, &protoObj) )
break;
if (protoInfo) {
itemNum = 0; /* protoInfo->subItemNum is always 0, so set itemNum
to 0 instead of protoInfo->subItemNum. */
protoInfo->subDesNode = protoDes->subDesList._cls->GetItem(
protoDes->subDesList._ctx, 0
);
protoDes->subDesList._cls->GetItemValue(
protoInfo->subDesNode, &desObj
);
}
protoInfo = (proto_info *) protoObj._ctx;
protoDes = protocol_parser_set_proto_info(
ctx, protoInfo, &desObj, itemNum, REF_CONDITION
);
if (protoDes->isCondition)
condition_backtrace_set(&ctx->condBacktrace, protoInfo);
ctx->protoInfoStack._cls->PushFront(
ctx->protoInfoStack._ctx, &protoObj
);
} while ( protoDes->subDesList._cls->GetItemCount(
protoDes->subDesList._ctx
) );
}
8)定義以下的函數用於初始化步驟3)定義的上下文:
static void protocol_parser_reset(protocol_parser_ctx * ctx) {
ctx->dataOffset = 0;
ctx->condBacktrace._cls->Clear(ctx->condBacktrace._ctx);
ctx->protoInfoStack._cls->Clear(ctx->protoInfoStack._ctx);
}
static bool protocol_parser_begin_parse(
ctx_t ctx, uint8_t * buffer, size_t bufSize, proto_des_obj * protoDesObj)
{
if (ctx && buffer && bufSize && protoDesObj &&
protoDesObj->_cls && protoDesObj->_ctx)
{
protocol_parser_ctx * parserCtx = (protocol_parser_ctx *) ctx;
parserCtx->dataBuf = buffer;
parserCtx->dataSize = bufSize;
protocol_parser_reset(parserCtx);
protocol_parser_push_proto_des(parserCtx, protoDesObj, 0);
return true;
}
return false;
}
9)定義以下的函數用於從步驟3)定義的上下文中解析出一個 proto_info 的實例:
static bool protocol_parser_parse(ctx_t ctx, proto_info * out_protoInfo) {
if (ctx) {
protocol_parser_ctx * parserCtx = (protocol_parser_ctx *) ctx;
list_obj * protoInfoStack = &(parserCtx->protoInfoStack);
node_t protoNode = protoInfoStack->_cls->GetItem(
protoInfoStack->_ctx, 0
);
if (protoNode) {
proto_info * protoInfo = 0;
const proto_des * protoDes = 0;
proto_info_obj protoObj = {0};
proto_des_obj subDesObj = {0};
proto_info subProtoInfo = {0};
const proto_des * subDes = 0;
protoInfoStack->_cls->GetItemValue(protoNode, &protoObj);
protoInfo = (proto_info *) protoObj._ctx;
protoDes = protoInfo->protoDes;
while (protoInfo->subDesNode) {
protoInfo->subDesNode = protoDes->subDesList._cls->GetItem(
protoDes->subDesList._ctx, protoInfo->subDesNode
);
if (!protoInfo->subDesNode) {
if ( ++(protoInfo->subItemNum) >= \
protoDes->Length(protoInfo) )
{
protoInfo->subItemNum = 0;
break;
}
protoInfo->subDesNode = protoDes->subDesList._cls->GetItem(
protoDes->subDesList._ctx, 0
);
}
protoDes->subDesList._cls->GetItemValue(
protoInfo->subDesNode, &subDesObj
);
subDes = protocol_parser_set_proto_info(
parserCtx,
&subProtoInfo,
&subDesObj,
protoInfo->subItemNum,
PEEK_CONDITION
);
if ( subDes->Length(&subProtoInfo) ) {
protocol_parser_push_proto_des(
parserCtx, &subDesObj, protoInfo->subItemNum
);
break;
}
if (subDes->condition) {
condition_backtrace_get(
&(parserCtx->condBacktrace),
subDes->condition,
REF_CONDITION
);
}
}
protoInfoStack->_cls->PopFront(
protoInfoStack->_ctx, &protoObj
);
protoInfo = (proto_info *) protoObj._ctx;
protoDes = protoInfo->protoDes;
if (protoDes->staticSize) {
parserCtx->dataOffset = \
protoInfo->dataOffset + protoDes->TotalSize(protoInfo);
}
if (parserCtx->dataOffset <= parserCtx->dataSize * 8) {
*out_protoInfo = *protoInfo;
operator_delete(&protoObj);
return true;
}
operator_delete(&protoObj);
protocol_parser_reset(parserCtx);
}
}
return false;
}
10)循環執行步驟9)定義的函數,直至返回 false 。如果是解析比特流,則即可獲得一個 proto_info 的序列;如果是填充比特流,則每獲得一個 proto_info 的實例,根據其信息填充相關的數據到緩衝區中。
一種通用的樹形二進制協議描述方法與處理算法
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章
python3:通過實例講解元類實現_ORM01
上海_彭彭
2018-11-08 05:19:49
python3:__new__和__init__魔法函數區別
上海_彭彭
2018-11-06 22:58:15
python3:聊聊 爲什麼要有@property裝飾器
上海_彭彭
2018-11-06 22:58:15
python:深度理解元類
上海_彭彭
2018-11-06 22:58:15
python3:屬性描述符(__get__,__set__,__delete__)
上海_彭彭
2018-11-06 22:58:15
C++語言中的元類編程(三)
vault13
2018-09-05 07:10:26
C++語言中的元類編程(五)
vault13
2018-09-05 07:10:26
C++語言中的元類編程(二)
vault13
2018-09-05 07:10:26
C++語言中的元類編程(四)
vault13
2018-09-05 07:10:26
C++語言中的元類編程(六)
vault13
2018-09-05 07:10:26
C++語言中的元類編程(八)
vault13
2018-09-05 07:10:26
C++語言中的元類編程(九)
vault13
2018-09-05 07:10:26
C++語言中的元類編程(七)
vault13
2018-09-05 07:10:26