昨天和一個老程序員吃飯聊起codelphi,說很久以前,經(jīng)常能從這里搜索到一些好的技術(shù)文章。
最近的工作也蠻辛苦。開始接觸以前從來沒有接觸過的GNU/linux下的基于gcc的開發(fā)。兩樣?xùn)|西都是現(xiàn)學(xué)的。工作了3個星期,只寫了一個
電信smgp3協(xié)議的tlv參數(shù)解析包。所謂的tlv參數(shù)就是(tag
,length,value),tag表示一個指令標志,length,表示這個指令所攜帶數(shù)據(jù)的長度,value表示指令所攜帶的數(shù)據(jù),用這種方式傳遞
參數(shù)可以很大程度的在不影響效率的情況下減少空參數(shù)所占的空間,節(jié)省網(wǎng)絡(luò)帶寬。貼部分代碼給大家指正
#ifndef _PTLV_HPP
#define _PTLV_HPP
#include <iostream>
#include <iomanip>
#include <string>
#include <sys/types.h>
/*sowpdu*/
typedef unsigned short WORD;
typedef unsigned char BYTE;
typedef int BOOL;
#ifndef TRUE
#define TRUE 1
#define FALSE 0
#endif
////////////////////////////////////////////////////////////////////////////////
/*
Name: PTlv
Copyright:
Author:
Date: 14-12-05 15:05
Description:
*/
class PTlv{
private:
WORD tag;//tlv 標識
WORD len; //value 長度
BYTE *value; //參數(shù)數(shù)據(jù)體
int byteOffset;
public:
PTlv(WORD new_tag, WORD new_len, BYTE *new_value);
PTlv(WORD new_tag, BYTE new_value);
PTlv();
void Clone(PTlv &src_tlv);
~PTlv();
enum VALUE_TYPE{ //
INTEGER_1 = 0x0001, //byte
INTEGER_2 = 0x0002, //word
OCTET_STRING = 0x0003 //string
};
enum TLV_Tag{
TLV_TP_PID = 0x0001, //GSM協(xié)議類型。詳細解釋請參考GSM03.40中的9.2.3.9
TLV_TP_UDHI = 0x0002, //GSM協(xié)議類型。詳細解釋請參考GSM03.40中的9.2.3.23,僅使用1位,右對齊。
TLV_LINK_ID = 0x0003, //交易標識,用于唯一標識一次交易
TLV_CHARGE_USER_TYPE = 0x0004, //計費用戶類型。
// 0=對短消息接收方計費;
// 1=對短消息發(fā)送方計費;
// 2=對SP計費;
// 3=表示本字段無效,對誰計費參見ChargeTermID或ChargeTermPseudo 字段。
TLV_CHARGE_TERM_TYPE = 0x0005, //計費用戶的號碼類型。
// 0=真實號碼;
// 1=偽碼;其它保留。
TLV_CHARGE_TERM_PSEUDO = 0x0006, //計費用戶的偽碼
TLV_DEST_TERM_TYPE = 0x0007, //短消息接收方的號碼類型。
// 0=真實號碼;
// 1=偽碼;其它保留
TLV_DEST_TERM_PSEUDO = 0x0008, //短消息接收方的偽碼,當有多個接收方偽碼時,要求每個接收方偽碼的長度一樣。
TLV_PK_TOTAL = 0x0009, //相同Msg_Id的消息總條數(shù)。
TLV_PK_NUMBER = 0x000A, //相同Msg_Id的消息序號,從1開始。
TLV_SUBMIT_MSG_TYPE = 0x000B, //SP發(fā)送的消息類型。
// 0=普通短消息;
// 1=WEB方式定制結(jié)果消息;
// 2=WEB方式取消定制結(jié)果消息;
// 3=終端方式定制結(jié)果消息;
// 4=終端方式取消定制結(jié)果消息;
// 5=包月扣費通知消息;
// 6=WEB方式定制二次確認消息;
// 7=WEB方式取消定制二次確認消息;
// 8=終端方式定制二次確認消息;
// 9=終端方式取消定制二次確認消息;
// 10=WEB方式點播二次確認消息;
// 11=終端方式點播二次確認消息(暫保留);
// 12=群發(fā)請求;
// 13:同步訂購(包括點播和定制)關(guān)系;
// 14:群發(fā)結(jié)果通知消息。
// 無該字段時,默認為"普通短消息"
// 15:同步訂購(包括點播和定制)關(guān)系回復(fù);其它保留;
TLV_SP_DEAL_RESLT = 0x000C, //SP對消息的處理結(jié)果
// 0=成功;
// 1=失敗;其它保留。
// 該字段在SubmitMsgType為0、5、6、7、8、9、10、11、14時無效。
TLV_SRC_TERM_TYPE = 0x000D, //短消息發(fā)送方的號碼類型。
// 0=真實號碼;
// 1=偽碼;其它保留。
TLV_SRC_TERM_PSEUDO = 0x000E, //短消息發(fā)送方的偽碼
TLV_NODES_COUNT = 0x000F, //經(jīng)過的網(wǎng)關(guān)數(shù)量。該字段的初始值為1。
TLV_MSG_SRC = 0x0010, //信息內(nèi)容的來源。
// 在固定網(wǎng)短消息業(yè)務(wù)中,MsgSrc填寫SP的服務(wù)代碼。
// 在移動網(wǎng)短消息業(yè)務(wù)中,MsgSrc填寫SP的企業(yè)代碼。
TLV_SRC_TYPE = 0x0011, //傳遞給SP 的源號碼的類型。
// 0=真實號碼;
// 1=偽碼;其它保留。
TLV_M_SERVICE_ID = 0x0012 //業(yè)務(wù)代碼。用于移動網(wǎng)業(yè)務(wù)
};
WORD getTag() const { return tag;}
void setTag(WORD new_tag){ tag = new_tag; }
WORD getTLVLen() const { return 2+2+len; }
WORD getValueLen() const { return len;}
int getOffset() const{ return byteOffset;}
BOOL getValue(BYTE *pstr, int value_len);
static BOOL IsValidTag(WORD the_tag);
static std::string AliasByTag(WORD the_tag);
BOOL Decode(BYTE *pstr, int tlv_len);
BOOL Encode(WORD the_tag, WORD the_len, BYTE *the_value);
BOOL Encode(WORD new_tag, BYTE new_value);
void PrintOn(std::ostream & strm) const;
void ToString(std::ostream & strm) const;
WORD getValueType(WORD the_tag) const;
protected:
};
////////////////////////////////////////////////////////////////////////////////
#endif //_TLV_HPP
//////////////////////////////tlv.cpp///////////////////////////////////////////////
#include "TLV.hpp"
// PTLV////////////////////////////////////////////////////////////////////
/**構(gòu)造器
*@param */
PTlv::PTlv(WORD new_tag, WORD new_len, BYTE *new_value){
Encode(new_tag, new_len, new_value);
}
PTlv::PTlv(WORD new_tag, BYTE new_value){
Encode(new_tag, new_value);
}
PTlv::PTlv(){
tag=0x0000;
len=0x0000;
value=0;
byteOffset=0;
}
/**/
void PTlv::Clone(PTlv &src_tlv){
tag = src_tlv.getTag();
len = src_tlv.getValueLen();
byteOffset= src_tlv.getOffset();
if(value != NULL) {
delete []value;
value = NULL;
}
value = new BYTE[len];
memset(value, 0, len);
src_tlv.getValue(value,len);
}
/*析構(gòu)器*/
PTlv::~PTlv(){
if (value != NULL)
delete []value;
value = NULL;
byteOffset = 0;
len = 0;
}
BOOL PTlv::IsValidTag(WORD the_tag){
switch(the_tag){
case TLV_TP_PID:// = 0x00000001,
case TLV_TP_UDHI:// = 0x00000002,
case TLV_LINK_ID:// = 0x00000003,
case TLV_CHARGE_USER_TYPE:// = 0x00000004,
case TLV_CHARGE_TERM_TYPE:// = 0x00000005,
case TLV_CHARGE_TERM_PSEUDO:// = 0x00000006,
case TLV_DEST_TERM_TYPE:// = 0x00000007,
case TLV_DEST_TERM_PSEUDO:// = 0x00000008,
case TLV_PK_TOTAL:// = 0x00000009,
case TLV_PK_NUMBER:// = 0x0000000A,
case TLV_SUBMIT_MSG_TYPE:// = 0x0000000B,
case TLV_SP_DEAL_RESLT:// = 0x0000000C,
case TLV_SRC_TERM_TYPE:// = 0x0000000D,
case TLV_SRC_TERM_PSEUDO:// = 0x0000000E,
case TLV_NODES_COUNT:// = 0x0000000F,
case TLV_MSG_SRC:// = 0x00000010,
case TLV_SRC_TYPE:// = 0x00000011,
case TLV_M_SERVICE_ID:// = 0x00000012,
return TRUE;
default :
return FALSE;
}
}
/**
* 取得tag的別名
* @param the_tag tag標識
* @return string 別名
*/
std::string PTlv::AliasByTag(WORD the_tag){
switch(the_tag){
case TLV_TP_PID:
return "TLV_TP_PID";
case TLV_TP_UDHI:
return "TLV_TP_UDHI";
case TLV_LINK_ID:
return "TLV_LINK_ID";
case TLV_CHARGE_USER_TYPE:
return "TLV_CHARGE_USER_TYPE";
case TLV_CHARGE_TERM_TYPE:
return "TLV_CHARGE_TERM_TYPE";
case TLV_CHARGE_TERM_PSEUDO:
return "TLV_CHARGE_TERM_PSEUDO";
case TLV_DEST_TERM_TYPE:
return "TLV_DEST_TERM_TYPE";
case TLV_DEST_TERM_PSEUDO:
return "TLV_DEST_TERM_PSEUDO";
case TLV_PK_TOTAL:
return "TLV_PK_TOTAL";
case TLV_PK_NUMBER:
return "TLV_PK_NUMBER";
case TLV_SUBMIT_MSG_TYPE:
return "TLV_SUBMIT_MSG_TYPE";
case TLV_SP_DEAL_RESLT:
return "TLV_SP_DEAL_RESLT";
case TLV_SRC_TERM_TYPE:
return "TLV_SRC_TERM_TYPE";
case TLV_SRC_TERM_PSEUDO:
return "TLV_SRC_TERM_PSEUDO";
case TLV_NODES_COUNT:
return "TLV_NODES_COUNT";
case TLV_MSG_SRC:
return "TLV_MSG_SRC";
case TLV_SRC_TYPE:
return "TLV_SRC_TYPE";
case TLV_M_SERVICE_ID:
return "TLV_M_SERVICE_ID";
default :
return "TLV_UNKNOWN_TAG_ID";
}
}
void PTlv::PrintOn(std::ostream &strm) const{
strm << "SMGP3_TLV:{\n";
strm << std::setw(15) << "tag:" << AliasByTag(tag)
<< " 0x" << std::hex <<
std::setw(sizeof(tag))<< std::setfill('0') << tag <<
'\n';
strm << std::setfill(' ') << std::setw(15) << "len:" << len << std::endl;
strm << std::setfill(' ') << std::setw(17) << "value:" << value <<std::endl;
strm << "}\n";
}
void PTlv::ToString(std::ostream &strm) const{
strm << "alias:" << AliasByTag(tag) << " len:"
<< len << " value:" << value <<'\n';
}
WORD PTlv::getValueType(WORD the_tag) const{
switch (the_tag) {
case TLV_TP_PID:
case TLV_CHARGE_USER_TYPE:
case TLV_CHARGE_TERM_TYPE:
case TLV_DEST_TERM_TYPE:
case TLV_PK_TOTAL:
case TLV_PK_NUMBER:
case TLV_SUBMIT_MSG_TYPE:
case TLV_SP_DEAL_RESLT:
case TLV_SRC_TERM_TYPE:
case TLV_NODES_COUNT:
case TLV_SRC_TYPE:
case TLV_TP_UDHI:{
return INTEGER_1;
break;
}
case TLV_CHARGE_TERM_PSEUDO:
case TLV_SRC_TERM_PSEUDO:
case TLV_DEST_TERM_PSEUDO:
case TLV_MSG_SRC:
case TLV_M_SERVICE_ID:
case TLV_LINK_ID:{
return OCTET_STRING; //20
break;
}
default :
return 0x00000000;
}
}
BOOL PTlv::getValue(BYTE *pstr, int value_len){
assert(len >0 );
assert(value != NULL );
if (value_len < len) return FALSE;
memset(pstr,0,value_len);
memcpy(pstr,value,len);
return TRUE;
}
BOOL PTlv::Decode(BYTE *pstr, int tlv_len){
memcpy(&tag, pstr, 2);
memcpy(&len, pstr+2, 2);
if (tlv_len < len) //tlv包長度必須大于value長度
return FALSE;
if (value != NULL) { //如果之前value有申請過空間,則先釋放他
delete[] value;
value = NULL;
}
byteOffset = 0;
value = new BYTE[len+1];
//memset(value, 0, len+1);
memcpy(value, pstr+4, len);
return TRUE;
}
BOOL PTlv::Encode(WORD the_tag, WORD the_len, BYTE *the_value){
assert(the_value != NULL);
assert(the_len > 0);
tag=the_tag;
if(value != NULL ){
delete [] value;
value = NULL;
}
value = new BYTE[the_len];
memset(value, 0, sizeof(BYTE)*the_len);
memcpy(value, (BYTE *)the_value, the_len);
len = the_len;
byteOffset = 0;
}
BOOL PTlv::Encode(WORD the_tag, BYTE the_value){
len=sizeof(BYTE);
tag = the_tag;
if (value != NULL){
delete [] value;
value = NULL;
}
value = new BYTE[len];
memset(value,0,sizeof(BYTE)*len);
byteOffset = 0;
value[byteOffset++] = the_value;
}