天天看點

WAP PUSH解析(1)——SMS PDU編碼一、單個SMS PDU的封裝二、多條SMS PDU的封裝三、小結            

田海立@CSDN

2012-06-29

WAP PUSH是封裝在SMS PDU中的,是以要解析WAP PUSH,首先要先看SMS PDU編碼,這是SMS / MMS / WAP PUSH等業務的基礎。WAP PUSH是通過發送給終端的,是以本文主要看Delivery類型的PDU編碼。另外,如果PDU要封裝的内容過長,會接收到拆分過的多條SMS,本文對接收到的多條Concatenated SMS的拼接也做了闡述。

一、單個SMS PDU的封裝

下面是接收到的一個完整PDU:

0891683108200105f04408a0015608860104216092902512236e0605040b8423f0120601ae02056a
0045c60c033231312e3133362e3130372e37382f646f776e2e7068703f703d413063303026733d38
3500080103e68e8ce68fa1e882a1e5b882e58588e69cbaefbc8ce6aca2e8bf8ee4bdbfe794a8e689
8be69cbae8af81e588b8e38082000101
           

(注:因顯示的原因,人為的進行了分行,其實這個包中間并沒有換行)

SMS PDU的封裝并不是在所有的位置都有固定的涵義,它是逐個掃描的,解析完上一個字段,才知道接下來的含義,或者後面字段的長度。

1. 短信中心

SC長度
      為08,是以接下來的8位元組為短信中心内容
   SC 91683108200105f0
      91為國際号,加上’+’号;
      後面的号碼編碼規則為GSM BCD:683108200105f0 –> 8613800210500
   是以,得到短信中心号碼:+8613800210500
           

現在PDU掃描到了紅色處(綠色部分已經掃描結束):

0891683108200105f04408a0015608860104216092902512236e0605040b8423f0120601ae02056a

0045c60c033231312e3133362e3130372e37382f646f776e2e7068703f703d413063303026733d38

3500080103e68e8ce68fa1e882a1e5b882e58588e69cbaefbc8ce6aca2e8bf8ee4bdbfe794a8e689

8be69cbae8af81e588b8e38082000101

2. FirstByte:

0x44 = 0100 0100
    bit1.bit0: mti
          00 Delevery
          01 Submit
          10 Status Report
    bit7: TP-Reply-Path
          1 有
          0 無
    bit6: 訓示是否有userdata header (UDH)
          1 有
          0 無
    bit4.bit3: TP-Validity-Period (submit類型的PDU才有意義)
          00: len=0
          10: len=1
          01/11: len=7
           

現在PDU掃描到了紅色處(綠色部分已經掃描結束):

0891683108200105f04408a0015608860104216092902512236e0605040b8423f0120601ae02056a

0045c60c033231312e3133362e3130372e37382f646f776e2e7068703f703d413063303026733d38

3500080103e68e8ce68fa1e882a1e5b882e58588e69cbaefbc8ce6aca2e8bf8ee4bdbfe794a8e689

8be69cbae8af81e588b8e38082000101

3. 發送方位址(Originating address)

位址長度: 
     長度Length = 08 
     得到位址占用的位元組數(包含長度本身): 2 + (Length + 1) / 2 = 6
     位址在08a001560886
   08 a001560886
   TOA: 0xA0 = 1010 0000
     bit7: 必須為1
     bit6...bit4: ton = 010
          000 TON_UNKNOWN(0)
          001 TON_INTERNATIONAL(1)
          010 TON_NATIONAL(2)
          011 TON_NETWORK(3)
          100 TON_SUBSCRIBER(4)
          101 TON_ALPHANUMERIC(5)
          110 TON_ABBREVIATED(6)
   是以,發送方位址為:
          01560886 
       -> 10658068
           

現在PDU掃描到了紅色處(綠色部分已經掃描結束):

0891683108200105f04408a0015608860104216092902512236e0605040b8423f0120601ae02056a

0045c60c033231312e3133362e3130372e37382f646f776e2e7068703f703d413063303026733d38

3500080103e68e8ce68fa1e882a1e5b882e58588e69cbaefbc8ce6aca2e8bf8ee4bdbfe794a8e689

8be69cbae8af81e588b8e38082000101

4. TP-Protocol-Identifier(TP-PID)

   TS 23.040 9.2.3.9      
   01      

現在PDU掃描到了紅色處(綠色部分已經掃描結束):

0891683108200105f04408a0015608860104216092902512236e0605040b8423f0120601ae02056a

0045c60c033231312e3133362e3130372e37382f646f776e2e7068703f703d413063303026733d38

3500080103e68e8ce68fa1e882a1e5b882e58588e69cbaefbc8ce6aca2e8bf8ee4bdbfe794a8e689

8be69cbae8af81e588b8e38082000101

5. TP-Data-Coding-Scheme

 (TS 23.038)      
0x04 = 0000 0100
     bit7: 如果此位為0
           bit6: automaticDeletion
           bit5: userDataCompressed
           bit4: hasMessageClass
           if (!userDataCompressed)  // bit5
              bit3...bit2: 
                00 ENCODING_7BIT
                10 ENCODING_16BIT
                01/11: ENCODING_8BIT
     bit7...bit4: 如果這四位為1111 
           bit2:
             0 ENCODING_7BIT
             1 ENCODING_8BIT
     Bit7...bit4: 如果這四位為1100, 1101 or 1110
           1110 ENCODING_16BIT(UCS-2)
           1100/1101 ENCODING_7BIT
     bit1...bit0: 如果有Class
           00 CLASS_0
           01 CLASS_1
           10 CLASS_2
           11 CLASS_3
   是以,這個PDU包資料是8Bit編碼,沒有Class類型。
           

現在PDU掃描到了紅色處(綠色部分已經掃描結束):  

0891683108200105f04408a0015608860104216092902512236e0605040b8423f0120601ae02056a

0045c60c033231312e3133362e3130372e37382f646f776e2e7068703f703d413063303026733d38

3500080103e68e8ce68fa1e882a1e5b882e58588e69cbaefbc8ce6aca2e8bf8ee4bdbfe794a8e689

8be69cbae8af81e588b8e38082000101

6.TP-Service-Centre-Time-Stamp

   短信中心下發的時間戳,這個編碼和長度固定      
21609290251223
   21 Year:   12
   60 Month:  06
   92 Day:    29
   90 Hour:   09
   25 Minute: 52
   12 Second: 21
   23 TimeZone Byte
     時區同樣高4bit在低位,低4bit在高位
     Bit3為時區+/-标志位
     計算的結果為1/4時區
     0x23 = 0010 0011
         Bit3: sign symbol
           0 +
           1 -
         0010 x011 -> x011 0010 = 0011 0010 = 32 [quarter-hour]
     TimeZone: + 32 / 4 = +8
           
   是以,得到時間戳為:12-06-29 09:52:21 GMT+8      

現在PDU掃描到了紅色處(綠色部分已經掃描結束):  

0891683108200105f04408a0015608860104216092902512236e0605040b8423f0120601ae02056a

0045c60c033231312e3133362e3130372e37382f646f776e2e7068703f703d413063303026733d38

3500080103e68e8ce68fa1e882a1e5b882e58588e69cbaefbc8ce6aca2e8bf8ee4bdbfe794a8e689

8be69cbae8af81e588b8e38082000101

7. UserDataHeader – UDH

UserDataLength: 長度包含UDH和UD,但不包含這個位元組本身
      0x6E = 110
    UserDataHeaderLength: 該長度不包含這個位元組本身
      0x06 = 6
    UserDataHeader: 05040b8423f0
      UDH中可能有多段,是以要不斷解析,直到UDH結束
      UDH每段含義開頭都有個id做标示,接下來是後面具體含義的資料的位元組個數,然後才是具體資料
      
      id - 0x05
        0x00 ELT_ID_CONCATENATED_8_BIT_REFERENCE
        0x08 ELT_ID_CONCATENATED_16_BIT_REFERENCE
        0x05 ELT_ID_APPLICATION_PORT_ADDRESSING_16_BIT
        0x04 ELT_ID_APPLICATION_PORT_ADDRESSING_8_BIT
        0x24 ELT_ID_NATIONAL_LANGUAGE_SINGLE_SHIFT
        0x25 ELT_ID_NATIONAL_LANGUAGE_LOCKING_SHIFT
      length: 4
      dest port: 0b84 -> 0x0B84 = 2948
          2948 for WAP_PUSH
      src port: 23f0 -> 0x23F0
           
   PDU是用端口來識别具體業務的,比如這個PDU的目的端口是2948,就是WAP PUSH的PDU封裝。      
   另外,如果還是長SMS,UDH中還會有長SMS拼接所需要的資訊,UDH中就有了多重的含義。      

現在PDU掃描到了紅色處(綠色部分已經掃描結束):  

0891683108200105f04408a0015608860104216092902512236e0605040b8423f0120601ae02056a

0045c60c033231312e3133362e3130372e37382f646f776e2e7068703f703d413063303026733d38

3500080103e68e8ce68fa1e882a1e5b882e58588e69cbaefbc8ce6aca2e8bf8ee4bdbfe794a8e689

8be69cbae8af81e588b8e38082000101

現在, PDU封裝的基本資訊已經解析完畢,剩下的是UserData,也已經區分出具體的業務,可以交給具體業務子產品去解析。

二、多條SMS PDU的封裝

因為單條SMS長度的限制,一條長SMS的發送是拆分成多條SMS發送的,接收時也是多條接收,然後拼接。

下面執行個體是分兩次接收到的一條長SMS的兩個SMS PDU:

PDU[0]

0891683108200105f04405a02125f00004216092717455238c0b05040b8423f000030b0201790601      
ae02056a0045c6080c03662e31303038362e636e2f662f736a6678000103e689bee69c8be58f8be3      
8081e69fa5e5a4a9e6b094e38081e79c8be5b08fe8afb4e38081e79c8be696b0e997bbe280a6e689      
8be69cbae9a39ee4bfa1efbc8ce7ae80e58d95e4bda0e79a84e7949fe6b4bbefbc81e8b5b6e5bfab      
e4b88be8bd      

PDU[1]

0891683108200105f04405a02125f0000421609271745523220b05040b8423f000030b0202bde4bd      
93e9aa8ce6898be69cbae9a39ee4bfa1000101      

UserDataHeader裡有多SMS的資訊,我們就從這裡開始分析。

1. UDH之前部分

PDU[0]與PDU[1]的UDH之前的部分完全相同,與前面講的單條SMS PDU的封裝也相同,是以這裡不再贅述這部分的解析。      

2. UserDataHeader– UDH

UserDataLength: 
      長度包含UDH和UD,但不包含這個位元組本身
      長度指的是本PDU中的長度
      PDU[0]: 0x8C = 140
      PDU[1]: 0x22 = 34
    UserDataHeaderLength: 該長度不包含這個位元組本身
      0x0B = 11
    UserDataHeader:
      UDH中可能有多段,是以要不斷解析,直到UDH結束
      UDH每段含義開頭都有個id做标示,接下來是後面具體含義的資料的位元組個數,然後才是具體資料
 
      PDU[0]: 05040b8423f0 00030b0201
      PDU[1]: 05040b8423f0 00030b0202
    
      id - 0x05
        0x00 ELT_ID_CONCATENATED_8_BIT_REFERENCE
        0x08 ELT_ID_CONCATENATED_16_BIT_REFERENCE
        0x05 ELT_ID_APPLICATION_PORT_ADDRESSING_16_BIT
        0x04 ELT_ID_APPLICATION_PORT_ADDRESSING_8_BIT
        0x24 ELT_ID_NATIONAL_LANGUAGE_SINGLE_SHIFT
        0x25 ELT_ID_NATIONAL_LANGUAGE_LOCKING_SHIFT
      length: 4
      dest port: 0b84 -> 0x0B84 = 2948
        2948 PORT_WAP_PUSH
      src port: 23f0 -> 0x23F0 
      這段說明這是WAP PUSH的PDU封裝
      
      id - 0x00
      length: 03
      ConcatRef.refNumber: 0B
      ConcatRef.msgCount: 02
      ConcatRef.seqNumber:
        PDU[0]: 01
        PDU[1]: 02
      這段說明這是長SMS的分拆出來的PDU封裝包:
        refNumber辨別是屬于哪個長SMS,分拆出來的各個分拆包都有相同的refNumber
        msgCount長SMS分拆出來的包的個數
        seqNumber訓示到達的該包在各個分拆包中的順序:取值1.. msgCount
                 因為分拆出來的包到達接收端的順序不一定是按次序的,是以拼接時,要按照這個順序。
           

3. UserData

這是一條長SMS拆分出的兩條,是以UserData要按seqNumber次序拼接起來。

PDU[0]

0891683108200105f04405a02125f00004216092717455238c0b05040b8423f000030b0201790601      
ae02056a0045c6080c03662e31303038362e636e2f662f736a6678000103e689bee69c8be58f8be3      
8081e69fa5e5a4a9e6b094e38081e79c8be5b08fe8afb4e38081e79c8be696b0e997bbe280a6e689      
8be69cbae9a39ee4bfa1efbc8ce7ae80e58d95e4bda0e79a84e7949fe6b4bbefbc81e8b5b6e5bfab      
e4b88be8bd      

PDU[1]

0891683108200105f04405a02125f0000421609271745523220b05040b8423f000030b0202bde4bd      
93e9aa8ce6898be69cbae9a39ee4bfa1000101      
把PDU[0]和PDU[1]中的紅色的UserData拼接起來,得到完整的UserData。      
790601ae02056a0045c6080c03662e31303038362e636e2f662f736a6678000103e689bee69c8be5      
8f8be38081e69fa5e5a4a9e6b094e38081e79c8be5b08fe8afb4e38081e79c8be696b0e997bbe280      
a6e6898be69cbae9a39ee4bfa1efbc8ce7ae80e58d95e4bda0e79a84e7949fe6b4bbefbc81e8b5b6      
e5bfabe4b88be8bdbde4bd93e9aa8ce6898be69cbae9a39ee4bfa1000101      

至此,完整的UserData已經得到,在UDH中也已經區分出具體的業務,可以交給具體業務子產品去解析。

三、小結            

Delivery SMS PDU中可以解析出:Service Centre(可無)、有無UDH、PDU類型的識别、發送方号碼、TP-PID、編碼格式、Class類型(可無)、時間戳、UDH(可無。含:UserData長度、UserDataHeader長度,可能有端口号或Concat資訊,等)以及包含具體業務資料的UserData。

關于UserData中具體WAP PUSH業務的封裝格式,在後續文章《WAP PUSH解析(2)——WSP以及WBXML編碼》和《WAP PUSH解析(3)——Android中實作》中解讀。