📄 dataformat.c
字号:
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include "sms.h"
#include "dataformat.h"
#include "errordef.h"
#include "smshandle.h"
#include "typedef.h"
int convsmsdata(const uchar* from, int fromlen, uchar* to, int* tolen, char flag);
int procpdudata(const uchar* indata, int inlen, PDU* pdu, uchar* outdata, int* outlen);
/************************************************************************/
/* Internal Functions
/************************************************************************/
/* 7-bit encoding and decoding */
int gsmEncode7bit(const char* pSrc, unsigned char* pDst, int nSrcLength);
int gsmDecode7bit(const unsigned char* pSrc, char* pDst, int nSrcLength);
/* 8-bit encoding and decoding */
int gsmEncode8bit(const uchar * pSrc, uchar * pDst, int nSrcLen);
int gsmDecode8bit(const uchar * pSrc, uchar * pDst, int nSrcLen);
/* UCS16-bit encoding to and decoding from GB coding */
int gsmEncodeGb2Uni(const uchar* pSrc, uchar* pDst, int nSrcLen);
int gsmDecodeUni2Gb(const uchar* pSrc, uchar* pDst, int nSrcLen);
char HexToChr(char ch);
char ChrToHex(char ch);
int reversedata(const char* pSrc, char* pDst, int nSrcLen);
int packpdudata(const uchar* indata, int inlen, PDU* inPdu, char* outdata, int* outlen);
int gsmEncodeUniNum(uchar *dest, const uchar *src, int len);
int gsmDecodeUniNum(uchar *dest, const uchar *src, int len);
extern void uni2gb(unsigned char *target,unsigned char *out);
extern void fast_gb2uni(unsigned char *target,unsigned char *out);
/*
* function: convert data format according to flag
* input params:
* from: input data buffer
* fromlen: the length of from
* flag: converting flag
* output params:
* to: output data buffer
* tolen: to's length after converting datas in input buffer
* return value:
* equal to 0: success to convert data
* less than 0: fail
*/
int convsmsdata(const uchar* from, int fromlen, uchar* to, int* tolen, char flag)
{
int outdatalen;
int ret;
switch(flag)
{
case ENCODE_7BIT:
outdatalen = gsmEncode7bit(from, to, fromlen);
break;
case CHAR_TO_HEX:
outdatalen = gsmEncode8bit(from, to, fromlen);
break;
case GB_TO_UCS16:
outdatalen = gsmEncodeGb2Uni(from, to, fromlen);
break;
case DECODE_7BIT:
outdatalen = gsmDecode7bit(from, to, fromlen);
break;
case HEX_TO_CHAR:
outdatalen = gsmDecode8bit(from, to, fromlen);
break;
case UCS16_TO_GB:
outdatalen = gsmDecodeUni2Gb(from, to, fromlen);
break;
case TO_UNI_NUM:
outdatalen = gsmEncodeUniNum(to, from, fromlen);
break;
case FR_UNI_NUM:
outdatalen = gsmDecodeUniNum(to, from, fromlen);
break;
default:
break;
}
if(outdatalen < 0)
{
WMMP_TRACE(debugType, "\r\nError: Convert data %d", outdatalen);
ret = -SMS_ERR_CONV_DATA;
goto convsmsdata_fail;
}
//get converted data length
*tolen = outdatalen;
return 0;
convsmsdata_fail:
return ret;
}
/*
* function: process PDU format data to PDU structure,
* and get the data and data's length.
* PDU data example:
* 0891 683108501945F4 040D91 685169005953F1 001560 016161651023 02FF00
* 0891+短信中心+消息类型+源址+编码方式+时间戳+短信内容
* 0891 683108501945F4 040D91 685169005953F1 00F060 016151615423 02421C
*/
int procpdudata(const uchar* indata, int inlen, PDU* pdu, uchar* outdata, int* outlen)
{
const uchar* pInData;
int nAddrLen, nLeftDataLen;
int nInDataInx;
uchar phase;
int ret;
uchar temp[3];
#define PDU_SMSC_LEN_PHASE 0x01
#define PDU_SMSC_TYPE_PHASE 0x02
#define PDU_SMSC_ADDR_PHASE 0x03
#define PDU_MSG_REF_PHASE 0x04
#define PDU_SRCADDR_LEN_PHASE 0x05
#define PDU_SRCADDR_TYPE_PHASE 0x06
#define PDU_SRCADDR_DATA_PHASE 0x07
#define PDU_PROTOID_PHASE 0x08
#define PDU_DCS_PHASE 0x09
#define PDU_VALID_PERI_PHASE 0x0A
#define PDU_TIME_STAMP_PHASE 0x0B
#define PDU_DATA_LEN_PHASE 0x0C
#define PDU_DATA_PHASE 0x0D
#define PDU_OVER_PHASE 0xFF
#define PDU_ERROR_PHASE 0xFE
pInData = indata;
nInDataInx = 0;
nLeftDataLen = inlen;
phase = PDU_SMSC_LEN_PHASE;
while (nLeftDataLen > 0)
{
switch(phase)
{
//08--SMSC address length 91--SMSC address type
//683108501945F4--SMSC address
case PDU_SMSC_LEN_PHASE:
memset(temp, 0, sizeof(temp));
ret = gsmDecode8bit(pInData, temp, 2);
if (ret < 0)
{
goto procpdudata_fail;
}
pdu->sc_addr_len = temp[0]; //get SMSC address length
pInData += 2; //move pInData forward 2
nLeftDataLen -= 2;
phase = PDU_SMSC_TYPE_PHASE;
break;
case PDU_SMSC_TYPE_PHASE:
memset(temp, 0, sizeof(temp));
ret = gsmDecode8bit(pInData, temp, 2);
if (ret < 0)
{
goto procpdudata_fail;
}
pdu->sc_addr_type = temp[0]; //get SMSC address type
pInData += 2;
nLeftDataLen -= 2;
phase = PDU_SMSC_ADDR_PHASE;
break;
case PDU_SMSC_ADDR_PHASE:
nAddrLen = pdu->sc_addr_len - 2; //get real SMS center address length, sc_addr_len must be even number
pInData += 2; //point to the first number of SMS center address
nLeftDataLen -= 2;
memset(pdu->sc_addr, 0, sizeof(pdu->sc_addr));
ret = reversedata(pInData, pdu->sc_addr, nAddrLen*2);
if (ret < 0)
{
goto procpdudata_fail;
}
if (pdu->sc_addr[nAddrLen*2 - 1] == 'F')
{
pdu->sc_addr[nAddrLen*2 - 1] = '\0'; //remove the last number'F'
}
pInData += nAddrLen*2; //move the pointer to the message reference
nLeftDataLen -= nAddrLen*2;
phase = PDU_MSG_REF_PHASE;
break;
//040D91 04--TP Message Reference 0D--source address length
//91--source address type
//685169005953F1--source address(important)
case PDU_MSG_REF_PHASE:
memset(temp, 0, sizeof(temp));
ret = gsmDecode8bit(pInData, temp, 2);
if (ret < 0)
{
goto procpdudata_fail;
}
pdu->tp_msg_refer = temp[0]; //get the TP Message Reference
pInData += 2; // move 2 bytes forwards
nLeftDataLen -= 2;
phase = PDU_SRCADDR_LEN_PHASE;
break;
case PDU_SRCADDR_LEN_PHASE:
memset(temp, 0, sizeof(temp));
ret = gsmDecode8bit(pInData, temp, 2);
if (ret < 0)
{
goto procpdudata_fail;
}
pdu->tp_da_len = temp[0]; //get the source address length
pInData += 2;
nLeftDataLen -= 2;
phase = PDU_SRCADDR_TYPE_PHASE;
break;
case PDU_SRCADDR_TYPE_PHASE:
memset(temp, 0, sizeof(temp));
ret = gsmDecode8bit(pInData, temp, 2);
if (ret < 0)
{
goto procpdudata_fail;
}
pdu->tp_da_type = temp[0]; //get the source address type
pInData += 2; //point to "68" of source address
nLeftDataLen -= 2;
phase = PDU_SRCADDR_DATA_PHASE;
break;
case PDU_SRCADDR_DATA_PHASE:
if (pdu->tp_da_len%2 == 0)
{
nAddrLen = pdu->tp_da_len - 2;
}
else
{
nAddrLen = pdu->tp_da_len - 1; //
}
pInData += 2; //point to the real first number of source addres
nLeftDataLen -= 2;
ret = reversedata(pInData, pdu->tp_daddr, nAddrLen);
if (ret < 0)
{
goto procpdudata_fail;
}
if (pdu->tp_daddr[nAddrLen - 1] == 'F')
{
pdu->tp_daddr[nAddrLen - 1] = '\0'; //remove the last 'F'
}
pInData += nAddrLen; //move pInData nAddrLen bytes forwards
nLeftDataLen -= nAddrLen;
phase = PDU_PROTOID_PHASE;
break;
//001560
//00--TP Protocol identifier 15--TP Data Coding Scheme(important)
//60--TP Valid Period
case PDU_PROTOID_PHASE:
memset(temp, 0, sizeof(temp));
ret = gsmDecode8bit(pInData, temp, 2);
if (ret < 0)
{
goto procpdudata_fail;
}
pdu->tp_pid = temp[0];//get TP Protocol identifier
pInData += 2;
nLeftDataLen -= 2;
phase = PDU_DCS_PHASE;
break;
case PDU_DCS_PHASE:
memset(temp, 0, sizeof(temp));
ret = gsmDecode8bit(pInData, temp, 2);
if (ret < 0)
{
goto procpdudata_fail;
}
pdu->tp_dcs = temp[0];//get TP data coding scheme
pInData += 2;
nLeftDataLen -= 2;
phase = PDU_VALID_PERI_PHASE;
break;
case PDU_VALID_PERI_PHASE:
memset(temp, 0, sizeof(temp));
ret = gsmDecode8bit(pInData, temp, 2);
if (ret < 0)
{
goto procpdudata_fail;
}
pdu->tp_vp = temp[0];//get TP valid period
pInData += 2;
nLeftDataLen -= 2;
phase = PDU_TIME_STAMP_PHASE;
break;
case PDU_TIME_STAMP_PHASE:
pInData += 12; //016161651023--time stamp(can be ignored)
nLeftDataLen -= 12;
phase = PDU_DATA_LEN_PHASE;
break;
//02FF00(important)
//02--data length FF00--data
case PDU_DATA_LEN_PHASE:
memset(temp, 0, sizeof(temp));
ret = gsmDecode8bit(pInData, temp, 2);
if (ret < 0)
{
goto procpdudata_fail;
}
*outlen = temp[0]*2;//get data length(real bytes)
pInData += 2;
nLeftDataLen -= 2;
phase = PDU_DATA_PHASE;
break;
case PDU_DATA_PHASE:
memcpy(outdata, pInData, *outlen);
nLeftDataLen -= *outlen;
phase = PDU_OVER_PHASE;
break;
default:
WMMP_TRACE(debugType, "\r\nError: unknown PDU phase");
break;
}
if (nLeftDataLen < 0)
{
WMMP_TRACE(debugType, "\r\nError: entire PDU data length");
goto procpdudata_fail;
}
if (phase == PDU_OVER_PHASE)
{
break;
}
}
return 0;
procpdudata_fail:
return ret;
}
/*
* Functions: package PDU-format data
* Input Params:
* indata: sending data; converted data 2-digit Hex
* inlen: length of sending data
* inPdu: pdu structure
* Output Params:
* outdata: packaged PDU-format data
* outlen: length of packaged PDU-format data not including SMSC 00
* Example: 00 11000D91 683106869031F5 0000A7 0431D98C06
*/
int packpdudata(const uchar* indata, int inlen, PDU* inPdu, char* outdata, int* outlen)
{
uchar* pOutData;
char dstaddr[20];
char indatalen;
int dstlen;
int ret, iOutLen;
pOutData = outdata;
iOutLen = 0;
//SMSC
//to do: test if SMSC is counted in total length
//SMSC is zero, because we have set is when call setsmsconfig()
*(pOutData + iOutLen) = 0x30;
*(pOutData + iOutLen + 1) = 0x30;
pOutData += 2;
//11--file header
ret = gsmEncode8bit(&(inPdu->tp_head), pOutData, 1);
if (ret < 0)
{
WMMP_TRACE(debugType, "\r\nError: tp_head");
goto packpdudata_fail;
}
iOutLen += 2;
pOutData += 2;
//00--message reference
ret = gsmEncode8bit(&(inPdu->tp_msg_refer), pOutData, 1);
if (ret < 0)
{
WMMP_TRACE(debugType, "\r\nError: tp_msg_refer");
goto packpdudata_fail;
}
iOutLen += 2;
pOutData += 2;
//0D--destination length
ret = gsmEncode8bit(&(inPdu->tp_da_len), pOutData, 1);
if (ret < 0)
{
WMMP_TRACE(debugType, "\r\nError: tp_da_len");
goto packpdudata_fail;
}
iOutLen += 2;
pOutData += 2;
//91--destination type
ret = gsmEncode8bit(&(inPdu->tp_da_type), pOutData, 1);
if (ret < 0)
{
WMMP_TRACE(debugType, "\r\nError: tp_da_type");
goto packpdudata_fail;
}
iOutLen += 2;
pOutData += 2;
//68+phone number
memset(dstaddr, 0, sizeof(dstaddr));
dstlen = strlen(inPdu->tp_daddr);
if (dstlen%2 == 0)
{
sprintf(dstaddr, "86%s", inPdu->tp_daddr);
}
else
{
sprintf(dstaddr, "86%sF", inPdu->tp_daddr);
}
ret = reversedata(dstaddr, pOutData, strlen(dstaddr));
if (ret < 0)
{
WMMP_TRACE(debugType, "\r\nError: tp_daddr");
goto packpdudata_fail;
}
iOutLen += strlen(dstaddr);
pOutData += strlen(dstaddr);
//00-message reference
ret = gsmEncode8bit(&(inPdu->tp_msg_refer), pOutData, 1);
if (ret < 0)
{
WMMP_TRACE(debugType, "\r\nError: tp_msg_refer");
goto packpdudata_fail;
}
iOutLen += 2;
pOutData += 2;
//08--Data Codeing Scheme
ret = gsmEncode8bit(&(inPdu->tp_dcs), pOutData, 1);
if (ret < 0)
{
WMMP_TRACE(debugType, "\r\nError: tp_dcs");
goto packpdudata_fail;
}
iOutLen += 2;
pOutData += 2;
//A7--valid periods
ret = gsmEncode8bit(&(inPdu->tp_vp), pOutData, 1);
if (ret < 0)
{
WMMP_TRACE(debugType, "\r\nError: tp_vp");
goto packpdudata_fail;
}
iOutLen += 2;
pOutData += 2;
//copy transformed data
//sms data length, Notion: 7-bit is different from 8-bit and UCS2 coding!!!
if (inPdu->tp_dcs == 0x00)
{
indatalen = inlen;
}
else
{
indatalen = strlen(indata)/2;
}
ret = gsmEncode8bit(&indatalen, pOutData, 1);
if (ret < 0)
{
WMMP_TRACE(debugType, "\r\nError: encode data length field");
goto packpdudata_fail;
}
iOutLen += 2;
pOutData += 2;
//sms data, transformed data(2-digit HEX)
memcpy(pOutData, indata, strlen(indata));
iOutLen += strlen(indata);
pOutData += strlen(indata);
//get outlen
*outlen = iOutLen/2;
return 0;
packpdudata_fail:
return ret;
}
char HexToChr(char ch)
{
if (ch <= 0x09 && ch>= 0x00)
{
ch = ch + 0x30;
}
else if (ch <= 0x0F && ch >= 0x0A)
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -