sexta-feira, 17 de dezembro de 2010

Por dentro do Component do Information Element (IE) Facility do protocolo DSS1

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
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

domingo, 12 de dezembro de 2010

Como fazer downloads a partir de uma máquina Linux sem interface gráfica

Apesar de ter trabalhado uns quatro anos com Solaris, não sei fazer muitas coisas usando somente linha de comando.

Uma das coisas que não nunca havia feito via linha de comando é download na Internet.

O comando mágico é o wget. Basta passar o link do download como parâmetro para o comando.

Testei o comando em um CentOS e funcionou muito bem:


]# wget http://www.smartfoxserver.com/products/download.php?d=76
--2010-12-12 13:20:26--  http://www.smartfoxserver.com/products/download.php?d=76
Resolving www.smartfoxserver.com... 62.149.227.100
Connecting to www.smartfoxserver.com|62.149.227.100|:80... connected.
HTTP request sent, awaiting response... 302 Found
Location: ../download/SFSPRO_linux_1.6.6.tar.gz [following]
--2010-12-12 13:20:27--  http://www.smartfoxserver.com/download/SFSPRO_linux_1.6.6.tar.gz
Connecting to www.smartfoxserver.com|62.149.227.100|:80... connected.
HTTP request sent, awaiting response... 200 OK
Length: 136461484 (130M) [application/x-gzip]
Saving to: `SFSPRO_linux_1.6.6.tar.gz'


100%[===================================================================================================================>] 136,461,484  221K/s   in 9m 2s


2010-12-12 13:29:29 (246 KB/s) - `SFSPRO_linux_1.6.6.tar.gz' saved [136461484/136461484]


Eu não precisei de nada avançado, mas dá para fazer milagres com o wget, como por exemplo, baixar um site inteiro. Veja mais detalhes na referência [1] .

Referência:
[1] http://www.simplehelp.net/2008/12/11/how-to-download-files-from-the-linux-command-line/

quarta-feira, 8 de dezembro de 2010

Como configurar uma página de erro HTTP 404 Page Not Found para Struts 2

Tive a simples missão de criar uma página para tratamento do erro HTTP 404 Page Not Found em um projeto usando Tomcat/Struts2/Spring.

Minha primeira idéia foi tentar resolver isso no struts.xml, mas depois de umas pesquisas fui direcionado a tentar resolver esse problema no web.xml, como seria feito em qualquer projeto Java Web:


  1. <?xml version="1.0" encoding="ISO-8859-1"?>  
  2. <web-app xmlns="http://java.sun.com/xml/ns/j2ee"  
  3. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  
  4. xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"  
  5. version="2.4">  
  6.    <display-name>Aplicacao web simples</display-name>  
  7.    <welcome-file-list>  
  8.      <welcome-file>/bemvindo.jsp</welcome-file>  
  9.    </welcome-file-list>  
  10.     <error-page>  
  11.         <error-code>404</error-code>  
  12.         <location>/erro.jsp</location>  
  13.     </error-page>  
  14. </web-app>

Isso não funcionou. Quando digitava uma página inexistente, a seguinte exceção era disparada e a página ficava em branco:

2010-12-08 14:50:43 Dispatcher [WARN] Could not find action or result
There is no Action mapped for namespace / and action name pan. - [unknown location]
at com.opensymphony.xwork2.DefaultActionProxy.prepare(DefaultActionProxy.java:178)
at org.apache.struts2.impl.StrutsActionProxy.prepare(StrutsActionProxy.java:61)
at org.apache.struts2.impl.StrutsActionProxyFactory.createActionProxy(StrutsActionProxyFactory.java:39)
at com.opensymphony.xwork2.DefaultActionProxyFactory.createActionProxy(DefaultActionProxyFactory.java:47)
at org.apache.struts2.dispatcher.Dispatcher.serviceAction(Dispatcher.java:478)
at org.apache.struts2.dispatcher.ng.ExecuteOperations.executeAction(ExecuteOperations.java:77)
at org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter.doFilter(StrutsPrepareAndExecuteFilter.java:91)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at org.springframework.orm.jpa.support.OpenEntityManagerInViewFilter.doFilterInternal(OpenEntityManagerInViewFilter.java:112)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:76)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:233)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:191)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:128)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:293)
at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:849)
at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:583)
at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:454)
at java.lang.Thread.run(Thread.java:619)


Após mais algumas pesquisas fui corretamente direcionado para a solução, e ela realmente estava no struts.xml. Não é necessária nenhuma configuração no web.xml. [1]

Basta configurar uma action default. Assim, quando o struts receber uma requisição que não der match com nenhuma action configurada, ela mandará para a sua página de erro personalizada. O struts.xml fica assim:


    <default-action-ref name="pageNotFound" />
    <action name="pageNotFound">
        <result>/pageNotFound.jsp</result>
    </action>


Comentários, sugestões, dicas e críticas são bem-vindas.


Links:
[1] http://struts.apache.org/2.0.14/docs/action-configuration.html
[2] http://wiki.metawerx.net/wiki/Web.xml.ErrorCode
[3] http://www.coderanch.com/t/428310/Struts/Interceptor-messes-up-action-class
[4] http://www.mkyong.com/struts2/there-is-no-action-mapped-for-namespace-and-action-name-youractionname/