本文以实例方式总结对CDMA Point-to-Point SMS 格式的学习。
首先,理清涉及的3GPP2 spec的主要内容和关联。首先从C.S0023-D_v2.0开始,在3.4.27 EFsms这一节中讲述了CDMA SMS的结构框架。我们得知:
1,CDMA SMS由三个部分组成:Status,Message Length,以及SMS Transport Layer Message三部分组成
2,Status,1个字节:01表示已读,03表示未读,05表示已发,07表示未发。
3,Message Len,1个字节:是 SMS Transport Layout Message的字节长度。最多255。
4,SMS Transport Layout Message,是消息体,具体说明在C.S0015-B_v2.0中,3.4节。
SMS Transport Layer Message结构
结构如下
Message Type:1个字节,00表示Point to Point; 01表示Broadcast;02表示Acknownledge
下面,我们只分析Point to Point类型的SMS,下面应该包括的内容结构如下:
跟spec上的内容有点区别,我把每个Parameter的ID号也列上去了。根据注解,如果是手机发出的SMS,那么Originating Address/Subaddress就没有;如果是手机收到的SMS,那么Destination Address/Subaddress就没有。
对于这些Parameter,总是按照这样的结构:
1,Parameter Id:每个部分的ID是固定的
2,Parameter Len : 是Parameter Data的字节个数
3,Parameter Data :这部分还可以进一步划分出子结构。
现在,我们对CDMA Point-to-Point SMS的主要结构应该有所了解。下面结合实例分析细节。
实例分析
03390000021002020C9004A9B6B0B93A333932B7000601FC0821000315D3F0010A104D3E9CB2E1DBA7767003061302051653280406130205200000
03: Status,未读。
39: MSG Len,表示后面有57个字节。
后面都是SMS Transport Layout Message的内容了。
00 MSG type,可知这是Point to Point类型的短消息。
00 这是Teleservice Identifier的ID值,所以可知后面是Teleservice的部分。
02 表示Teleservice 的LEN,后面2个字节
1002表示CDMA Identifier,值4098,参考N.S0005-0 v1.0 Table 175。对于CDMA SMS这个值固定。
02 这是Originating Address的ID值,可知后面的部分是发信人的信息。
0C 表示Originating Address的Len,后面有12个字节。
9004A9B6B0B93A333932B700 这个串要扩展开再分析了。
90 04 1/0/01 0/000 0/000 0100 根据spec,依次是digit mode/number mode/number type/number plan,最后还剩7bits。下面依次解释:
1,digit mode,可知address digit用8bit ASCII编码地址,而不是4bit DTMF编码。
0,number mode,可知address type不是data network address。如果是email地址做为发件人,这里要设为1。
010, number type。如果digit mode是0,此处就忽略,不用设置;如果digit mode 是1,就要看number mode的设置了,如果number mode是1,要从Table 3.4.3.3-1中对比,如果number mode是0,就要从Table 2.7.1.3.2.4-2中对比。所以,可知是national number。
0000, number plan 。如果digit mode是0,或者number mode是1,此处就忽略,不用设置了。如果digit mode是1,number mode是0,就从Table 2.7.1.3.2.4-3中对比。所以,可知是Unkown。
还剩下7个bits: 0000100,根据spec,还有一个number of fields,但是它8bits的,所以需要和后面的部分连接起来分析。
需要从头开始,4个bit重新划分,最后补0,以便对齐1个字节:
第一个字节0000 1001,就是number of fields,值为9,表示address中有9个字符。而剩下的53 6D 61 72 74 66 72 65 6E 就是发送者的地址了,也就是“Smartfren”。它是印尼的一个电信运营商。注意这里发信人的地址不是电话号码,而是字符串哦。
剩下的部分:0601FC0821000315D3F0010A104D3E9CB2E1DBA7767003061302051653280406130205200000
接着是0601FC。
06,可知到了Bearer Reply Option这部分了。这个部分是用来针对Acknownledge Message,请求一个return用的,不过我们已经知道这是一个P2P类型的短消息。
01,可知后面只有1个字节。
FC, 1111 11/00,根据spec,是reply seq/reserved。这里设置reply sequence number是111111,即63。
接下来,
08,可知到了Bearer Data的部分。
21,可知后面33个字节。根据spec,后面都是subparameter的部分了,参考C.S0015-B_v2.0 4.5节的内容。
这里每一个subparameter也是类似于parameter的结构:
SUBPARAMETER_ID 1个字节
SUBPARAMETER_LEN 1个字节, subparamater data的字节个数
Subparamater Data SUBPARAMETER_LEN的值个字节
所有的subparamter,如下表,Bearer Data可以由其中1个,或多个组成。可见Bearer Data可以内容可以很多的。
好吧,顺序分析这些Subparameter:000315D3F0010A104D3E9CB2E1DBA7767003061302051653280406130205200000
00,可知到了Message Identifier这个subparamter了。
03,可知后面3个字节。
15 D3 F0, 0001 / 0101 1101 0011 1111/ 0/000 根据spec,分别是message type/message id/header ind/reserved。根据Table 4.5.1-1,可知这个短息是Deliver类型的,即从Smartfren发给手机的。Deliver即MT的意思。后面的message id是ISP分配的。herder ind为0,表示后面的User Data Subparameter没有header。
接下来,
01,可知到了User Data的部分。
0A,可知后面10个字节。
104D3E9CB2E1DBA77670,这里根据spec,又需要扩展开来分析。
10 4D, 0001 0/000 0100 1/101 MSG_ENCODING/NUM_FILEDS,最后还剩下3bits。根据C.R1001-F_v1.0的Table 9.1-1,可知Encoding是7bit ASCII,这里和发信人的编码是不同的,那个是8bit ASCII,待会分析的时候要做转换才可以。根据spec,本来还有一个MSG_TYPE的部分,但是只有当MSG_ENCODING是0x01,或者0x0A时,才有意义,否则可以忽略,不设置。最后NUM_FILEDS的值为9,表示这个短消息的内容只有9个字符。下面,我们就分析消息的内容是什么。
注意最开始是上1个字节剩下的3bits。上面分析出来,这是7bit ASCII编码,我们需要转换成8bit ASCII,才能分析出来它们的内容。转换的方法,就是把上面的2进制串,按7bit分组,然后每组前面加一个0。如下
这样就变成了53 74 72 65 61 6D 69 6e 67,也就是字符串“Streaming”。至此,我们可知这个短消息的内容了。
再来,
03,表示到了Message Center Time Stamp的部分
06,表示后面有6个字节。
130205165328,这个就很简单了,表示2013.2.5 16:53:28。
最后一小段,
04,表示到了Validity Period - Absolute
06,表示后面有6个字节。
130205200000,表示2013.2.5 20:00:00
至此,全部内容都分析完了。
还有一个关于size的问题。在实际开发中,我们可能需要构造某种类型的SMS,以便测试,若只是构造一个简单的英文内容的短消息,可以根据上面的分析,反导,最后要涉及到一个size的问题。我们从结构上看一下这条短消息:
status
msg len 57个字节
msg type 1个字节
teleservice:
id
len 2个字节
data
originating address:
id
len 12个字节
data
number of fields 8个字符
bearer reply option:
id
len 1个字节
data
bearer data:
id
len 33个字节
sub parameter:
id
len 3个字节
data
sub parameter:
id
len 10个字节
data
number of fields 9个字符
sub parameter:
id
len 6个字节
data
sub parameter:
id
len 6个字节
data
1,bearer data有33个字节,但是那些sub parameter的len,加起来:3 + 10 +6 +6=25个字节,为什么不一致?这是因为subparameter len只是表示后面的字节数,所以每一个subparameter还应该再加2个字节,这样就是25 + 2 x 4,就是33了。对于MSG Len也是类似的。57个字节 = 1 + 2 + 12 +1 +33,再加 2 x 4,因为msg type没有parameter len的。
2,对于bearer data中的user data,有可能subparameter len会比number of fields的值还要小,因为如果按照7bit ASCII编码,等于是压缩了一些。要注意的是number of fields是实际字符的个数,而不是字节的个数。对于Originating address,也是类似的情况。
总结
1,这条短消息,发信人是“Smartfren”,非国际号码,内容是“Streaming”,发信人以8bit ASCII编码,内容以7bit ASCII编码。
2,分析的重点和难点,在于发信人地址,以及内容的分析,一方面需要仔细理解spec中的规范,另一方面涉及编码转换的认识。本文还仅仅涉及英文内容,如果是东亚编码,转换上将会困难和麻烦一些。
3,本文仅起到介绍的作用,方便有需要的同行理解3gpp2的规范。我在开发中遇到这个需要,遍查网络,没找到满意答案,自学后总结出来,备忘。