Vou registrar o conhecimento adquirido por mim e pelo meu amigo Bruno Oliveira para a posteridade.
Depois de muito bater cabeça entendemos como codificar/decodificar um componente de cabo a rabo.
Vamos usar um exemplo para ficar mais fácil. Vamos decodificar o componente abaixo:
A1-1B-02-02-00-A0-06-06-04-00- 82-67-01-08-30-0D-0A-01-00-02- 01-00-40-05-04-03-80-90-A3
Component Type
O primeiro octeto é o tipo de componente. Existem quatro tipos de componentes:
A1 = Invoke
A2 = Return Result
A3 = Return Error
A4 = Reject
No nosso caso o primeiro octeto é A1, então é um Invoke Component.
* [1] capítulo 23.4.1
Component Lenght
A segunda informação a ser extraída é o tamanho do octeto. O lenght pode ser codificado usando 1, 2 ou 3 octetos, de acordo com a tablela abaixo
Tamanho - Codificação - Octetos usados
0 a 127 - XX - Octeto 2
128 a 255 - 81-XX - Octeto 2 e 3
256 a 1023 - 82-XX-XX - Octeto 2, 3 e 4
Resumindo o quadro:
* se o segundo octeto do component é 81, o lenght tá no terceiro octeto
* se o segundo octeto do component é 82, o lenght tá no terceiro e no quarto octeto
* se o segundo octeto não é nem 81, nem 82, o lenght é o segundo octeto em si
No nosso caso o segundo octeto é 1B, logo o lengh é ele mesmo. 0x1B é 27 em decimal. Pode contar, após o lenght, temos 27 octetos no exemplo.
* [1] capítulo 23.4.1
Tag
A terceira informação é o Tag. Pode ser Tag para Invoke Id ou Tag para NULL (usado em caso de erro)
O Tag para Invoke ID é 02 e para Null é 05.
No nosso caso p terceiro octeto é 02, logo um Tag para Invoke Id.
* [1] capítulo 23.4.1 e 23.4.4
Lenght of Invoke Id
A quarta informação é o tamanho do Invoke Id.
Esse campo é de somente um octeto.
No nosso caso, o quarto octeto é 02, então o tamanho do Invoke Id é de dois octetos.
* [1] capítulo 23.4
Invoke Id
O Invoke Id é divido em quatro faixas:
A | 0 a 127 | 1 octeto
B | 128 a 32767 | 2 octeto
C | -32768 a -129 | 2 octeto
D | -128 a -1 | 1 octeto
O octetos é sinalizado (o bit mais significativo indica o sinal).
Como já vimos que o tamanho é 2, nosso Invoke Id é 00-A0.
Como o bit mais significativo é 0, sabemos que é Invoke Id da faixa B e seu valor em decimal é 160.
* [1] capítulo 23.1
------------------------------ ------------------------------ ------------------------------ ------------------------------ ------------------------------ -----
Nesse ponto podemos parar para um café.
Bom, já decodificamos A1-1B-02-02-00-A0
Ainda falta 06-06-04-00-82-67-01-08-30-0D- 0A-01-00-02-01-00-40-05-04-03- 80-90-A3
Tomou café? So, let´s go!
------------------------------ ------------------------------ ------------------------------ ------------------------------ ------------------------------ -----
Operation-value
A próxima informação a ser extraída é a operação. Esse informação que define o quê você quer fazer dentro do tipo de componente que você está.
* [1] capítulo 4
Esse campo está codificado segundo o ASN.1 e BER. O tipo de dado utilizado é um CCBSOID, que em grosso modo é uma classe que extende o tipo Object Identifier.
Na codificação BER, é usada uma técnica chamada TLV (Type, Length, Value).
* [2]
Type of Operation-value
Nessa codificação o type é definido no primeiro octeto.
Nosso primeiro octeto é 06:
0000 0110
Os bits 8 e 7 são a classe. No nosso caso 00 e significa que o tipo de dados é Universal (conhecido por qq organização).
O bit 6 é um flag. Quando 0 significa Primitive (tipo de dados primitivo). Quando 1 significa Constructed. Tipo de dados derivado.
Os bits de 5 a 1 são o Number, que indica que tipo de dado é. No nosso caso é 6, indicando um OBJECT IDENTIFIER.
* [2]
Length of Operation-value
O segundo octeto é o tamanho do tipo de dados.
No nosso caso 06, dizendo que o dado está nos próximos 6 octetos.
Content of Operation-value
O OBJECT IDENTIFIER é uma informação de identificação única no mundo. Não existem dois objetos no mundo com o mesmo object identifer.
O registro dos Objects Identifiers fica a cargo da ITU-T. Quando algum maluco prentende definir um objeto que poderá ser conhecido por qq empresa no mundo ele tem que fazer o registro.
* [3]
A codificação de um Object Identifier segue a norma X.209 da CCITT. Essa norma foi substituída pela X.690 da ITU-T.
O Object identifier é uma sequência de números onde cada parte tem seu significado próprio.
Vou usar a notação de pontos para dar um exemplo. o Object Identifier 0.3.2044 deve ser interpretado assim:
O primeiro campo, 0, significa qual é o organismo de padronização. Zero significa CCITT ou ITU-T.
De acordo com o primeiro campo o segundo campo muda de semântica. Nesse caso o segundo campo, 3, significa network-operator.
A história se repete. De acordo com o segundo campo, o terceiro tem o seu significado. Nesse caso 2044 significa "NETHERLANDS Unisource / Unidata"
Isso foi só um exemplo de Object Identifier. Agora a gente vai decodificar isso aí.
O OID é uma sequencia de octetos onde os valores são codificados usando apenas 7 bits. O oitavo bit é um indicador que o próximo octeto deve ser usado para ser agrupado com o atual para se chegar no número desejado.
Tem mais um if. As duas primeiras clases são codificadas no primeirto octeto. Assim, no OID X.Y.Z.A.B , as classes X e Y são codificadas no mesmo octeto.
A regra para essa codificação é: (X*40)+Y
* [4] capítulo 22
Vamos trabalhar com o nosso OID 04-00-82-67-01-08
Sabemos que o primeiro octeto, 04, contém duas classes e conhecemos a sua codificação então...
Extraindo-se os 7 bits continuamos continuamos com 0x04 e 4 em decimal.
Dividindo por 40 temos o quociente e o resto. O quociente é o X e o resto é o Y.
Logo nosso OID começa com "0.4".
Vamos para o próximo octeto, 00. No work to do here. Agora temos 0.4.0.
Vamos para o proxímo octeto, 82. Como o bit mais ignificativo está setado a gente tem que pegar o próximo octeto também que é 67.
Temos que pegar somente os 7 bits de cada um, logo
000 010 e 110 0111, juntando os bits temos: 0000 0001 e 0110 0111 que dá 0x167, 359 em decimal. Agora temos 0.4.0.359.
Ainda temos o 01 e 08, mas esses não exigem esforço e por isso completamos nosso CCBSOID:0.4.0.359.1.8
O significado dele é CCBSStatusRequest.
* [1] capítulo 22.1.75
* [5] capítulo 7 table 3
Isso mesmo... Esse trabalho todo para descobrir que a operação a ser realizada é um CCBSStatusRequest.
------------------------------ ------------------------------ ------------------------------ ------------------------------ ------------------------------ -----
Mais um café?
Bom, já decodificamos A1-1B-02-02-00-A0
E 06-06-04-00-82-67-01-08
Ainda falta 30-0D-0A-01-00-02-01-00-40-05- 04-03-80-90-A3
Tomou café? So, let´s go!
------------------------------ ------------------------------ ------------------------------ ------------------------------ ------------------------------ -----
CCBS Status Request
Os campos dessa operação são Recall Mode, CCBS Reference, Q931 Information Element.
* [1] capítulo 16.1.1 página 153.
* [5] capítulo 7 table 3
Continuamos seguindo a história do TLV.
O primeiro octeto é 0x30, 0011 0000, logo:
Class Universal: 0
Contructed: 1
Number: 16 = Sequence
O segundo octeto é o tamanho: 0x0D, 13 em decimal.
O CCBSStuatusRequest é 0A-01-00-02-01-00-40-05-04-03- 80-90-A3
Recall Mode
Continuamos com o TLV para extrair o RecallMode. O Octeto em questão é o 0x0A, 0000 1010.
Class Universal: 0
Primitive: 0
Number: 10 = Enumerated
O tamanho é 0x01 e o valor é 0x00.
O Recall Mode é um tipo ENUMERATED indicando Global Recall (0) ou Specifica Recall (1). Logo nosso Recall Mode = Global Recall
* [1] capítulo 28.1.88
CCBS Reference
Ok, só falta 02-01-00-40-05-04-03-80-90-A3. Vamos para o CCBS Reference.
O Octeto em questão é o 0x02, 0000 0010.
Class Universal: 0
Primitive: 0
Number: 2 = Integer
O tamanho é 0x01 e o valor é 0x00, logo, CCBS Reference = 0;
Q931 Information Element
O octeto restante é 40-05-04-03-80-90-A3
Continuamos com o TLV. O Octeto em questão é o 0x40, 0100 0000.
Class Application: 1
Primitive: 0
Number: 0 (depende da aplicação, precisamos olhar na ASN.1 do CCBS)
O tamanho é 0x05 e o valor é 04-03-80-90-A3.
Esses 5 octetos representam um IE do DSS1. Agora podemos nos basear na FS do DSS1 da Ericsson [7].
O primeiro octeto é o IE Identifier. 0x04 é o id do Bearer capability.
O segundo octeto é o lenght, logo temos q analisar 3 octetos.
O terceiro octeto traz duas informações:
Coding Standard = 00 = CCITT standardizeted
Information Transfer Capability = 00000 = Speech
O quarto octeto também traz duas informações:
Transfer Mode = 00 = Circuit mode
Information Transfer Rate = 10000 = 64 kbits
O quinto, e último, octeto indica o User Information Layer 1 Protocol = Rec. G.711 A-law
------------------------------ ------------------------------ ------------------------------ ------------------------------ ------------------------------ -----
Referências:
1 - Test Component Data Specification
2 - BER: Basic Enconding Rules
3 - Object Identifier Repository
4 - X.209 - Specification of Basic Encoding Rules for Abstract Syntax Notation One (ASN.1)
5 - ETSI EN 300 359-1 v1.3.2 - CCBS Protocol Specification
6 - ETSI EN 300 196-1 v1.3.2 - Generic function protocol for supporting supplementary services, DSS1 - Protocol Specification
7 - DSS1 Layer 3 Protocol Specification
8 - Der ISDN-D-Kanal